object_rainbow/numeric/
private.rs1use std::{fmt::Display, num::NonZero};
2
3use crate::{enumkind::UsizeTag, *};
4
5pub trait HasOtherSign {
6 type OtherSign;
7}
8
9type Os<T> = <T as HasOtherSign>::OtherSign;
10
11#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Le<T>(pub T);
14#[derive(ParseAsInline, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct Be<T>(pub T);
17
18impl<T: Display> Display for Le<T> {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 self.0.fmt(f)
21 }
22}
23
24impl<T: Display> Display for Be<T> {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 self.0.fmt(f)
27 }
28}
29
30impl<T> Le<T> {
31 pub const fn new(value: T) -> Self {
32 Self(value)
33 }
34}
35
36impl<T> Be<T> {
37 pub const fn new(value: T) -> Self {
38 Self(value)
39 }
40}
41
42impl<T> From<T> for Be<T> {
43 fn from(n: T) -> Self {
44 Self(n)
45 }
46}
47
48impl<T> From<T> for Le<T> {
49 fn from(n: T) -> Self {
50 Self(n)
51 }
52}
53
54impl<T> Deref for Le<T> {
55 type Target = T;
56
57 fn deref(&self) -> &Self::Target {
58 &self.0
59 }
60}
61
62impl<T> Deref for Be<T> {
63 type Target = T;
64
65 fn deref(&self) -> &Self::Target {
66 &self.0
67 }
68}
69
70pub trait AsLe {
71 type Le;
72 fn construct(self) -> Self::Le;
73}
74
75pub trait AsBe {
76 type Be;
77 fn construct(self) -> Self::Be;
78}
79
80macro_rules! signs {
81 ($u:ty, $i:ty) => {
82 impl HasOtherSign for $u {
83 type OtherSign = $i;
84 }
85 impl HasOtherSign for $i {
86 type OtherSign = $u;
87 }
88 };
89}
90
91macro_rules! ae {
92 ($n:ty) => {
93 impl UsizeTag for $n {
94 fn from_usize(n: usize) -> Self {
95 n.try_into().expect("discriminant out of range")
96 }
97 fn to_usize(&self) -> usize {
98 (*self).try_into().expect("discriminant out of range")
99 }
100 fn try_to_usize(&self) -> Option<usize> {
101 (*self).try_into().ok()
102 }
103 }
104
105 impl UsizeTag for NonZero<$n> {
106 fn from_usize(n: usize) -> Self {
107 Self::new(
108 n.checked_add(1)
109 .expect("discriminant out of range")
110 .try_into()
111 .expect("discriminant out of range"),
112 )
113 .unwrap()
114 }
115 fn to_usize(&self) -> usize {
116 usize::try_from(self.get())
117 .expect("discriminant out of range")
118 .checked_sub(1)
119 .unwrap()
120 }
121 fn try_to_usize(&self) -> Option<usize> {
122 usize::try_from(self.get()).ok()?.checked_sub(1)
123 }
124 }
125
126 impl AsLe for $n {
127 type Le = Self;
128 fn construct(self) -> Self::Le {
129 self
130 }
131 }
132
133 impl AsLe for NonZero<$n> {
134 type Le = Self;
135 fn construct(self) -> Self::Le {
136 self
137 }
138 }
139
140 impl AsBe for $n {
141 type Be = Self;
142 fn construct(self) -> Self::Be {
143 self
144 }
145 }
146
147 impl AsBe for NonZero<$n> {
148 type Be = Self;
149 fn construct(self) -> Self::Be {
150 self
151 }
152 }
153
154 impl ToOutput for NonZero<$n> {
155 fn to_output(&self, output: &mut impl Output) {
156 self.get().to_output(output);
157 }
158 }
159
160 impl<I: ParseInput> Parse<I> for NonZero<$n> {
161 fn parse(input: I) -> crate::Result<Self> {
162 ParseInline::parse_as_inline(input)
163 }
164 }
165
166 impl<I: ParseInput> ParseInline<I> for NonZero<$n> {
167 fn parse_inline(input: &mut I) -> crate::Result<Self> {
168 NonZero::new(input.parse_inline::<$n>()?).ok_or(Error::Zero)
169 }
170 }
171
172 impl Size for NonZero<$n> {
173 const SIZE: usize = <$n as Size>::SIZE;
174 type Size = <$n as Size>::Size;
175 }
176
177 impl MaybeHasNiche for $n {
178 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
179 }
180
181 impl MaybeHasNiche for NonZero<$n> {
182 type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
183 }
184
185 impl Tagged for $n {}
186 impl Tagged for NonZero<$n> {}
187 impl ListHashes for $n {}
188 impl ListHashes for NonZero<$n> {}
189 impl Topological for $n {}
190 impl Topological for NonZero<$n> {}
191
192 impl Equivalent<$n> for Option<NonZero<$n>> {
193 fn into_equivalent(self) -> $n {
194 self.map(NonZero::get).unwrap_or_default()
195 }
196 fn from_equivalent(object: $n) -> Self {
197 NonZero::new(object)
198 }
199 }
200
201 impl Equivalent<Os<$n>> for $n {
202 fn into_equivalent(self) -> Os<$n> {
203 self as _
204 }
205 fn from_equivalent(object: Os<$n>) -> Self {
206 object as _
207 }
208 }
209
210 impl Equivalent<NonZero<Os<$n>>> for NonZero<$n> {
211 fn into_equivalent(self) -> NonZero<Os<$n>> {
212 NonZero::new(self.get() as _).unwrap()
213 }
214 fn from_equivalent(object: NonZero<Os<$n>>) -> Self {
215 NonZero::new(object.get() as _).unwrap()
216 }
217 }
218 };
219}
220
221macro_rules! lebe {
222 ($n:ty) => {
223 impl UsizeTag for $n {
224 fn from_usize(n: usize) -> Self {
225 n.try_into().expect("discriminant out of range")
226 }
227 fn to_usize(&self) -> usize {
228 (*self).try_into().expect("discriminant out of range")
229 }
230 fn try_to_usize(&self) -> Option<usize> {
231 (*self).try_into().ok()
232 }
233 }
234
235 impl UsizeTag for NonZero<$n> {
236 fn from_usize(n: usize) -> Self {
237 Self::new(
238 n.checked_add(1)
239 .expect("discriminant out of range")
240 .try_into()
241 .expect("discriminant out of range"),
242 )
243 .unwrap()
244 }
245 fn to_usize(&self) -> usize {
246 usize::try_from(self.get())
247 .expect("discriminant out of range")
248 .checked_sub(1)
249 .unwrap()
250 }
251 fn try_to_usize(&self) -> Option<usize> {
252 usize::try_from(self.get()).ok()?.checked_sub(1)
253 }
254 }
255
256 impl AsLe for $n {
257 type Le = Le<$n>;
258 fn construct(self) -> Self::Le {
259 Le(self)
260 }
261 }
262
263 impl AsLe for NonZero<$n> {
264 type Le = Le<NonZero<$n>>;
265 fn construct(self) -> Self::Le {
266 Le(self)
267 }
268 }
269
270 impl AsBe for $n {
271 type Be = Be<$n>;
272 fn construct(self) -> Self::Be {
273 Be(self)
274 }
275 }
276
277 impl AsBe for NonZero<$n> {
278 type Be = Be<NonZero<$n>>;
279 fn construct(self) -> Self::Be {
280 Be(self)
281 }
282 }
283
284 impl ToOutput for Le<$n> {
285 fn to_output(&self, output: &mut impl Output) {
286 if output.is_real() {
287 output.write(&self.0.to_le_bytes());
288 }
289 }
290 }
291
292 impl ToOutput for Be<$n> {
293 fn to_output(&self, output: &mut impl Output) {
294 if output.is_real() {
295 output.write(&self.0.to_be_bytes());
296 }
297 }
298 }
299
300 impl ToOutput for Le<NonZero<$n>> {
301 fn to_output(&self, output: &mut impl Output) {
302 if output.is_real() {
303 output.write(&self.0.get().to_le_bytes());
304 }
305 }
306 }
307
308 impl ToOutput for Be<NonZero<$n>> {
309 fn to_output(&self, output: &mut impl Output) {
310 if output.is_real() {
311 output.write(&self.0.get().to_be_bytes());
312 }
313 }
314 }
315
316 impl InlineOutput for Le<$n> {}
317 impl InlineOutput for Be<$n> {}
318
319 impl<I: ParseInput> ParseInline<I> for Le<$n> {
320 fn parse_inline(input: &mut I) -> crate::Result<Self> {
321 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
322 }
323 }
324
325 impl<I: ParseInput> ParseInline<I> for Be<$n> {
326 fn parse_inline(input: &mut I) -> crate::Result<Self> {
327 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
328 }
329 }
330
331 impl<I: ParseInput> ParseInline<I> for Le<NonZero<$n>> {
332 fn parse_inline(input: &mut I) -> crate::Result<Self> {
333 NonZero::new(input.parse_inline::<Le<$n>>()?.0)
334 .ok_or(Error::Zero)
335 .map(Le)
336 }
337 }
338
339 impl<I: ParseInput> ParseInline<I> for Be<NonZero<$n>> {
340 fn parse_inline(input: &mut I) -> crate::Result<Self> {
341 NonZero::new(input.parse_inline::<Be<$n>>()?.0)
342 .ok_or(Error::Zero)
343 .map(Be)
344 }
345 }
346
347 impl Size for Le<$n> {
348 const SIZE: usize = std::mem::size_of::<$n>();
349 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
350 }
351
352 impl Size for Be<$n> {
353 const SIZE: usize = std::mem::size_of::<$n>();
354 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
355 }
356
357 impl MaybeHasNiche for Le<$n> {
358 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
359 }
360
361 impl MaybeHasNiche for Be<$n> {
362 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
363 }
364
365 impl MaybeHasNiche for Le<NonZero<$n>> {
366 type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
367 }
368
369 impl MaybeHasNiche for Be<NonZero<$n>> {
370 type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
371 }
372
373 impl Tagged for Le<$n> {}
374 impl Tagged for Le<NonZero<$n>> {}
375 impl Tagged for Be<$n> {}
376 impl Tagged for Be<NonZero<$n>> {}
377 impl ListHashes for Le<$n> {}
378 impl ListHashes for Le<NonZero<$n>> {}
379 impl ListHashes for Be<$n> {}
380 impl ListHashes for Be<NonZero<$n>> {}
381 impl Topological for Le<$n> {}
382 impl Topological for Le<NonZero<$n>> {}
383 impl Topological for Be<$n> {}
384 impl Topological for Be<NonZero<$n>> {}
385
386 impl Size for Le<NonZero<$n>> {
387 const SIZE: usize = <Le<$n> as Size>::SIZE;
388 type Size = <Le<$n> as Size>::Size;
389 }
390
391 impl Size for Be<NonZero<$n>> {
392 const SIZE: usize = <Be<$n> as Size>::SIZE;
393 type Size = <Be<$n> as Size>::Size;
394 }
395
396 impl Equivalent<Le<$n>> for Option<Le<NonZero<$n>>> {
397 fn into_equivalent(self) -> Le<$n> {
398 Le(self.map(|object| object.0.get()).unwrap_or_default())
399 }
400 fn from_equivalent(object: Le<$n>) -> Self {
401 NonZero::new(object.0).map(Le)
402 }
403 }
404
405 impl Equivalent<Be<$n>> for Option<Be<NonZero<$n>>> {
406 fn into_equivalent(self) -> Be<$n> {
407 Be(self.map(|object| object.0.get()).unwrap_or_default())
408 }
409 fn from_equivalent(object: Be<$n>) -> Self {
410 NonZero::new(object.0).map(Be)
411 }
412 }
413
414 impl Equivalent<Le<Os<$n>>> for Le<$n> {
415 fn into_equivalent(self) -> Le<Os<$n>> {
416 Le(self.0 as _)
417 }
418 fn from_equivalent(object: Le<Os<$n>>) -> Self {
419 Le(object.0 as _)
420 }
421 }
422
423 impl Equivalent<Be<Os<$n>>> for Be<$n> {
424 fn into_equivalent(self) -> Be<Os<$n>> {
425 Be(self.0 as _)
426 }
427 fn from_equivalent(object: Be<Os<$n>>) -> Self {
428 Be(object.0 as _)
429 }
430 }
431
432 impl Equivalent<Le<NonZero<Os<$n>>>> for Le<NonZero<$n>> {
433 fn into_equivalent(self) -> Le<NonZero<Os<$n>>> {
434 Le(NonZero::new(self.0.get() as _).unwrap())
435 }
436 fn from_equivalent(object: Le<NonZero<Os<$n>>>) -> Self {
437 Le(NonZero::new(object.0.get() as _).unwrap())
438 }
439 }
440
441 impl Equivalent<Be<NonZero<Os<$n>>>> for Be<NonZero<$n>> {
442 fn into_equivalent(self) -> Be<NonZero<Os<$n>>> {
443 Be(NonZero::new(self.0.get() as _).unwrap())
444 }
445 fn from_equivalent(object: Be<NonZero<Os<$n>>>) -> Self {
446 Be(NonZero::new(object.0.get() as _).unwrap())
447 }
448 }
449 };
450}
451
452macro_rules! float {
453 ($n:ty) => {
454 impl AsLe for $n {
455 type Le = Le<$n>;
456 fn construct(self) -> Self::Le {
457 Le(self)
458 }
459 }
460
461 impl AsBe for $n {
462 type Be = Be<$n>;
463 fn construct(self) -> Self::Be {
464 Be(self)
465 }
466 }
467
468 impl ToOutput for Le<$n> {
469 fn to_output(&self, output: &mut impl Output) {
470 if output.is_real() {
471 output.write(&self.0.to_le_bytes());
472 }
473 }
474 }
475
476 impl ToOutput for Be<$n> {
477 fn to_output(&self, output: &mut impl Output) {
478 if output.is_real() {
479 output.write(&self.0.to_be_bytes());
480 }
481 }
482 }
483
484 impl InlineOutput for Le<$n> {}
485 impl InlineOutput for Be<$n> {}
486
487 impl<I: ParseInput> ParseInline<I> for Le<$n> {
488 fn parse_inline(input: &mut I) -> crate::Result<Self> {
489 Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
490 }
491 }
492
493 impl<I: ParseInput> ParseInline<I> for Be<$n> {
494 fn parse_inline(input: &mut I) -> crate::Result<Self> {
495 Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
496 }
497 }
498
499 impl Size for Le<$n> {
500 const SIZE: usize = std::mem::size_of::<$n>();
501 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
502 }
503
504 impl Size for Be<$n> {
505 const SIZE: usize = std::mem::size_of::<$n>();
506 type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
507 }
508
509 impl MaybeHasNiche for Le<$n> {
510 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
511 }
512
513 impl MaybeHasNiche for Be<$n> {
514 type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
515 }
516
517 impl ListHashes for Le<$n> {}
518 impl ListHashes for Be<$n> {}
519 impl Topological for Le<$n> {}
520 impl Topological for Be<$n> {}
521 impl Tagged for Le<$n> {}
522 impl Tagged for Be<$n> {}
523 };
524}
525
526signs!(u8, i8);
527signs!(u16, i16);
528signs!(u32, i32);
529signs!(u64, i64);
530signs!(u128, i128);
531
532ae!(u8);
533ae!(i8);
534
535lebe!(u16);
536lebe!(i16);
537
538lebe!(u32);
539lebe!(i32);
540
541lebe!(u64);
542lebe!(i64);
543
544lebe!(u128);
545lebe!(i128);
546
547float!(f32);
548float!(f64);
549
550#[test]
551fn nonzero() {
552 assert_eq!(Option::<super::Le<u8>>::SIZE, 2);
553 assert_eq!(Option::<super::Le<NonZero<u8>>>::SIZE, 1);
554 assert_eq!(Option::<super::Le<u16>>::SIZE, 3);
555 assert_eq!(Option::<super::Le<NonZero<u16>>>::SIZE, 2);
556}
557
558impl<T: UsizeTag> UsizeTag for Le<T> {
559 fn from_usize(n: usize) -> Self {
560 Self(UsizeTag::from_usize(n))
561 }
562
563 fn to_usize(&self) -> usize {
564 self.0.to_usize()
565 }
566
567 fn try_to_usize(&self) -> Option<usize> {
568 self.0.try_to_usize()
569 }
570}
571
572impl<T: UsizeTag> UsizeTag for Be<T> {
573 fn from_usize(n: usize) -> Self {
574 Self(UsizeTag::from_usize(n))
575 }
576
577 fn to_usize(&self) -> usize {
578 self.0.to_usize()
579 }
580
581 fn try_to_usize(&self) -> Option<usize> {
582 self.0.try_to_usize()
583 }
584}