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)]
12pub struct Ae<T>(pub T);
13#[derive(ParseAsInline)]
14pub struct Le<T>(pub T);
15#[derive(ParseAsInline)]
16pub struct Be<T>(pub T);
17#[derive(ParseAsInline)]
18pub struct Nz<T: NonZeroable>(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 Object for Ae<$n> {}
195        impl Inline 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 Object for Le<$n> {}
372        impl Object for Be<$n> {}
373        impl Inline for Le<$n> {}
374        impl Inline 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
432signs!(u8, i8);
433signs!(u16, i16);
434signs!(u32, i32);
435signs!(u64, i64);
436signs!(u128, i128);
437
438ae!(u8);
439ae!(i8);
440
441lebe!(u16);
442lebe!(i16);
443
444lebe!(u32);
445lebe!(i32);
446
447lebe!(u64);
448lebe!(i64);
449
450lebe!(u128);
451lebe!(i128);
452
453impl<T: NonZeroable> Deref for Nz<T> {
454    type Target = T::Nz;
455
456    fn deref(&self) -> &Self::Target {
457        &self.0
458    }
459}
460
461impl<T: NonZeroable + ToOutput> ToOutput for Nz<T> {
462    fn to_output(&self, output: &mut dyn Output) {
463        T::from_nz(&self.0).to_output(output);
464    }
465}
466
467impl<T: NonZeroable + ParseInline<I>, I: ParseInput> ParseInline<I> for Nz<T> {
468    fn parse_inline(input: &mut I) -> crate::Result<Self> {
469        Ok(Self(T::parse_inline(input)?.to_nz().ok_or(Error::Zero)?))
470    }
471}
472
473impl<T: NonZeroable + Size> Size for Nz<T> {
474    type Size = T::Size;
475}
476
477impl<T: NonZeroable + Size> MaybeHasNiche for Nz<T> {
478    type MnArray = SomeNiche<ZeroNiche<T::Size>>;
479}
480
481impl<T: NonZeroable> Topological for Nz<T> {}
482impl<T: NonZeroable> Tagged for Nz<T> {}
483impl<T: NonZeroable + ReflessInline> ReflessObject for Nz<T> {}
484impl<T: NonZeroable + ReflessInline> ReflessInline for Nz<T> {}
485impl<T: NonZeroable + Inline> Object for Nz<T> {}
486impl<T: NonZeroable + Inline> Inline for Nz<T> {}
487
488#[test]
489fn nonzero() {
490    assert_eq!(Option::<Ae<u8>>::SIZE, 2);
491    assert_eq!(Option::<Nz<Ae<u8>>>::SIZE, 1);
492    assert_eq!(Option::<Le<u16>>::SIZE, 3);
493    assert_eq!(Option::<Nz<Le<u16>>>::SIZE, 2);
494}