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