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