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 dyn crate::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 dyn Output) {
286                output.write(&self.0.to_le_bytes());
287            }
288        }
289
290        impl ToOutput for Be<$n> {
291            fn to_output(&self, output: &mut dyn Output) {
292                output.write(&self.0.to_be_bytes());
293            }
294        }
295
296        impl ToOutput for Le<NonZero<$n>> {
297            fn to_output(&self, output: &mut dyn Output) {
298                output.write(&self.0.get().to_le_bytes());
299            }
300        }
301
302        impl ToOutput for Be<NonZero<$n>> {
303            fn to_output(&self, output: &mut dyn Output) {
304                output.write(&self.0.get().to_be_bytes());
305            }
306        }
307
308        impl InlineOutput for Le<$n> {}
309        impl InlineOutput for Be<$n> {}
310
311        impl<I: ParseInput> ParseInline<I> for Le<$n> {
312            fn parse_inline(input: &mut I) -> crate::Result<Self> {
313                Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
314            }
315        }
316
317        impl<I: ParseInput> ParseInline<I> for Be<$n> {
318            fn parse_inline(input: &mut I) -> crate::Result<Self> {
319                Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
320            }
321        }
322
323        impl<I: ParseInput> ParseInline<I> for Le<NonZero<$n>> {
324            fn parse_inline(input: &mut I) -> crate::Result<Self> {
325                NonZero::new(input.parse_inline::<Le<$n>>()?.0)
326                    .ok_or(Error::Zero)
327                    .map(Le)
328            }
329        }
330
331        impl<I: ParseInput> ParseInline<I> for Be<NonZero<$n>> {
332            fn parse_inline(input: &mut I) -> crate::Result<Self> {
333                NonZero::new(input.parse_inline::<Be<$n>>()?.0)
334                    .ok_or(Error::Zero)
335                    .map(Be)
336            }
337        }
338
339        impl Size for Le<$n> {
340            const SIZE: usize = std::mem::size_of::<$n>();
341            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
342        }
343
344        impl Size for Be<$n> {
345            const SIZE: usize = std::mem::size_of::<$n>();
346            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
347        }
348
349        impl MaybeHasNiche for Le<$n> {
350            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
351        }
352
353        impl MaybeHasNiche for Be<$n> {
354            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
355        }
356
357        impl MaybeHasNiche for Le<NonZero<$n>> {
358            type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
359        }
360
361        impl MaybeHasNiche for Be<NonZero<$n>> {
362            type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
363        }
364
365        impl Tagged for Le<$n> {}
366        impl Tagged for Le<NonZero<$n>> {}
367        impl Tagged for Be<$n> {}
368        impl Tagged for Be<NonZero<$n>> {}
369        impl ListHashes for Le<$n> {}
370        impl ListHashes for Le<NonZero<$n>> {}
371        impl ListHashes for Be<$n> {}
372        impl ListHashes for Be<NonZero<$n>> {}
373        impl Topological for Le<$n> {}
374        impl Topological for Le<NonZero<$n>> {}
375        impl Topological for Be<$n> {}
376        impl Topological for Be<NonZero<$n>> {}
377
378        impl Size for Le<NonZero<$n>> {
379            const SIZE: usize = <Le<$n> as Size>::SIZE;
380            type Size = <Le<$n> as Size>::Size;
381        }
382
383        impl Size for Be<NonZero<$n>> {
384            const SIZE: usize = <Be<$n> as Size>::SIZE;
385            type Size = <Be<$n> as Size>::Size;
386        }
387
388        impl Equivalent<Le<$n>> for Option<Le<NonZero<$n>>> {
389            fn into_equivalent(self) -> Le<$n> {
390                Le(self.map(|object| object.0.get()).unwrap_or_default())
391            }
392            fn from_equivalent(object: Le<$n>) -> Self {
393                NonZero::new(object.0).map(Le)
394            }
395        }
396
397        impl Equivalent<Be<$n>> for Option<Be<NonZero<$n>>> {
398            fn into_equivalent(self) -> Be<$n> {
399                Be(self.map(|object| object.0.get()).unwrap_or_default())
400            }
401            fn from_equivalent(object: Be<$n>) -> Self {
402                NonZero::new(object.0).map(Be)
403            }
404        }
405
406        impl Equivalent<Le<Os<$n>>> for Le<$n> {
407            fn into_equivalent(self) -> Le<Os<$n>> {
408                Le(self.0 as _)
409            }
410            fn from_equivalent(object: Le<Os<$n>>) -> Self {
411                Le(object.0 as _)
412            }
413        }
414
415        impl Equivalent<Be<Os<$n>>> for Be<$n> {
416            fn into_equivalent(self) -> Be<Os<$n>> {
417                Be(self.0 as _)
418            }
419            fn from_equivalent(object: Be<Os<$n>>) -> Self {
420                Be(object.0 as _)
421            }
422        }
423
424        impl Equivalent<Le<NonZero<Os<$n>>>> for Le<NonZero<$n>> {
425            fn into_equivalent(self) -> Le<NonZero<Os<$n>>> {
426                Le(NonZero::new(self.0.get() as _).unwrap())
427            }
428            fn from_equivalent(object: Le<NonZero<Os<$n>>>) -> Self {
429                Le(NonZero::new(object.0.get() as _).unwrap())
430            }
431        }
432
433        impl Equivalent<Be<NonZero<Os<$n>>>> for Be<NonZero<$n>> {
434            fn into_equivalent(self) -> Be<NonZero<Os<$n>>> {
435                Be(NonZero::new(self.0.get() as _).unwrap())
436            }
437            fn from_equivalent(object: Be<NonZero<Os<$n>>>) -> Self {
438                Be(NonZero::new(object.0.get() as _).unwrap())
439            }
440        }
441    };
442}
443
444macro_rules! float {
445    ($n:ty) => {
446        impl AsLe for $n {
447            type Le = Le<$n>;
448            fn construct(self) -> Self::Le {
449                Le(self)
450            }
451        }
452
453        impl AsBe for $n {
454            type Be = Be<$n>;
455            fn construct(self) -> Self::Be {
456                Be(self)
457            }
458        }
459
460        impl ToOutput for Le<$n> {
461            fn to_output(&self, output: &mut dyn Output) {
462                output.write(&self.0.to_le_bytes());
463            }
464        }
465
466        impl ToOutput for Be<$n> {
467            fn to_output(&self, output: &mut dyn Output) {
468                output.write(&self.0.to_be_bytes());
469            }
470        }
471
472        impl InlineOutput for Le<$n> {}
473        impl InlineOutput for Be<$n> {}
474
475        impl<I: ParseInput> ParseInline<I> for Le<$n> {
476            fn parse_inline(input: &mut I) -> crate::Result<Self> {
477                Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
478            }
479        }
480
481        impl<I: ParseInput> ParseInline<I> for Be<$n> {
482            fn parse_inline(input: &mut I) -> crate::Result<Self> {
483                Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
484            }
485        }
486
487        impl Size for Le<$n> {
488            const SIZE: usize = std::mem::size_of::<$n>();
489            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
490        }
491
492        impl Size for Be<$n> {
493            const SIZE: usize = std::mem::size_of::<$n>();
494            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
495        }
496
497        impl MaybeHasNiche for Le<$n> {
498            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
499        }
500
501        impl MaybeHasNiche for Be<$n> {
502            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
503        }
504
505        impl ListHashes for Le<$n> {}
506        impl ListHashes for Be<$n> {}
507        impl Topological for Le<$n> {}
508        impl Topological for Be<$n> {}
509        impl Tagged for Le<$n> {}
510        impl Tagged for Be<$n> {}
511    };
512}
513
514signs!(u8, i8);
515signs!(u16, i16);
516signs!(u32, i32);
517signs!(u64, i64);
518signs!(u128, i128);
519
520ae!(u8);
521ae!(i8);
522
523lebe!(u16);
524lebe!(i16);
525
526lebe!(u32);
527lebe!(i32);
528
529lebe!(u64);
530lebe!(i64);
531
532lebe!(u128);
533lebe!(i128);
534
535float!(f32);
536float!(f64);
537
538#[test]
539fn nonzero() {
540    assert_eq!(Option::<super::Le<u8>>::SIZE, 2);
541    assert_eq!(Option::<super::Le<NonZero<u8>>>::SIZE, 1);
542    assert_eq!(Option::<super::Le<u16>>::SIZE, 3);
543    assert_eq!(Option::<super::Le<NonZero<u16>>>::SIZE, 2);
544}
545
546impl<T: UsizeTag> UsizeTag for Le<T> {
547    fn from_usize(n: usize) -> Self {
548        Self(UsizeTag::from_usize(n))
549    }
550
551    fn to_usize(&self) -> usize {
552        self.0.to_usize()
553    }
554
555    fn try_to_usize(&self) -> Option<usize> {
556        self.0.try_to_usize()
557    }
558}
559
560impl<T: UsizeTag> UsizeTag for Be<T> {
561    fn from_usize(n: usize) -> Self {
562        Self(UsizeTag::from_usize(n))
563    }
564
565    fn to_usize(&self) -> usize {
566        self.0.to_usize()
567    }
568
569    fn try_to_usize(&self) -> Option<usize> {
570        self.0.try_to_usize()
571    }
572}