Skip to main content

object_rainbow/numeric/
private.rs

1use 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}