object_rainbow/numeric/
private.rs

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