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>(T);
13#[derive(ParseAsInline)]
14pub struct Le<T>(T);
15#[derive(ParseAsInline)]
16pub struct Be<T>(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}
71
72pub trait AsBe {
73    type Be;
74}
75
76macro_rules! signs {
77    ($u:ty, $i:ty) => {
78        impl HasOtherSign for $u {
79            type OtherSign = $i;
80        }
81        impl HasOtherSign for $i {
82            type OtherSign = $u;
83        }
84    };
85}
86
87macro_rules! ae {
88    ($n:ty) => {
89        impl UsizeTag for $n {
90            fn from_usize(n: usize) -> Self {
91                n.try_into().expect("discriminant out of range")
92            }
93            fn to_usize(&self) -> usize {
94                (*self).try_into().expect("discriminant out of range")
95            }
96            fn try_to_usize(&self) -> Option<usize> {
97                (*self).try_into().ok()
98            }
99        }
100
101        impl UsizeTag for NonZero<$n> {
102            fn from_usize(n: usize) -> Self {
103                Self::new(
104                    n.checked_add(1)
105                        .expect("discriminant out of range")
106                        .try_into()
107                        .expect("discriminant out of range"),
108                )
109                .unwrap()
110            }
111            fn to_usize(&self) -> usize {
112                usize::try_from(self.get())
113                    .expect("discriminant out of range")
114                    .checked_sub(1)
115                    .unwrap()
116            }
117            fn try_to_usize(&self) -> Option<usize> {
118                usize::try_from(self.get()).ok()?.checked_sub(1)
119            }
120        }
121
122        impl AsLe for $n {
123            type Le = Ae<$n>;
124        }
125
126        impl AsLe for NonZero<$n> {
127            type Le = Nz<Ae<$n>>;
128        }
129
130        impl AsBe for $n {
131            type Be = Ae<$n>;
132        }
133
134        impl AsBe for NonZero<$n> {
135            type Be = Nz<Ae<$n>>;
136        }
137
138        impl From<NonZero<$n>> for Nz<Ae<$n>> {
139            fn from(nz: NonZero<$n>) -> Self {
140                Self(nz)
141            }
142        }
143
144        impl NonZeroable for Ae<$n> {
145            type Nz = NonZero<$n>;
146            fn to_nz(&self) -> Option<Self::Nz> {
147                NonZero::new(self.0)
148            }
149            fn from_nz(nz: &Self::Nz) -> Self {
150                Self(nz.get())
151            }
152        }
153
154        impl ToOutput for Ae<$n> {
155            fn to_output(&self, output: &mut dyn Output) {
156                output.write(&self.0.to_le_bytes());
157            }
158        }
159
160        impl<I: ParseInput> ParseInline<I> for Ae<$n> {
161            fn parse_inline(input: &mut I) -> crate::Result<Self> {
162                Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
163            }
164        }
165
166        impl Size for Ae<$n> {
167            const SIZE: usize = std::mem::size_of::<$n>();
168            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
169        }
170
171        impl MaybeHasNiche for Ae<$n> {
172            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
173        }
174
175        impl Topological for Ae<$n> {
176            fn accept_points(&self, _: &mut impl PointVisitor) {}
177        }
178
179        impl Tagged for Ae<$n> {}
180        impl Tagged for Ae<NonZero<$n>> {}
181        impl ReflessObject for Ae<$n> {}
182        impl ReflessInline for Ae<$n> {}
183        impl Object for Ae<$n> {}
184        impl Inline for Ae<$n> {}
185
186        impl Equivalent<Ae<$n>> for Option<Ae<NonZero<$n>>> {
187            fn into_equivalent(self) -> Ae<$n> {
188                Ae(self.map(|object| object.0.get()).unwrap_or_default())
189            }
190            fn from_equivalent(object: Ae<$n>) -> Self {
191                NonZero::new(object.0).map(Ae)
192            }
193        }
194
195        impl Equivalent<Ae<Os<$n>>> for Ae<$n> {
196            fn into_equivalent(self) -> Ae<Os<$n>> {
197                Ae(self.0 as _)
198            }
199            fn from_equivalent(object: Ae<Os<$n>>) -> Self {
200                Ae(object.0 as _)
201            }
202        }
203
204        impl Equivalent<Ae<NonZero<Os<$n>>>> for Ae<NonZero<$n>> {
205            fn into_equivalent(self) -> Ae<NonZero<Os<$n>>> {
206                Ae(NonZero::new(self.0.get() as _).unwrap())
207            }
208            fn from_equivalent(object: Ae<NonZero<Os<$n>>>) -> Self {
209                Ae(NonZero::new(object.0.get() as _).unwrap())
210            }
211        }
212    };
213}
214
215macro_rules! lebe {
216    ($n:ty) => {
217        impl UsizeTag for $n {
218            fn from_usize(n: usize) -> Self {
219                n.try_into().expect("discriminant out of range")
220            }
221            fn to_usize(&self) -> usize {
222                (*self).try_into().expect("discriminant out of range")
223            }
224            fn try_to_usize(&self) -> Option<usize> {
225                (*self).try_into().ok()
226            }
227        }
228
229        impl UsizeTag for NonZero<$n> {
230            fn from_usize(n: usize) -> Self {
231                Self::new(
232                    n.checked_add(1)
233                        .expect("discriminant out of range")
234                        .try_into()
235                        .expect("discriminant out of range"),
236                )
237                .unwrap()
238            }
239            fn to_usize(&self) -> usize {
240                usize::try_from(self.get())
241                    .expect("discriminant out of range")
242                    .checked_sub(1)
243                    .unwrap()
244            }
245            fn try_to_usize(&self) -> Option<usize> {
246                usize::try_from(self.get()).ok()?.checked_sub(1)
247            }
248        }
249
250        impl AsLe for $n {
251            type Le = Le<$n>;
252        }
253
254        impl AsLe for NonZero<$n> {
255            type Le = Nz<Le<$n>>;
256        }
257
258        impl AsBe for $n {
259            type Be = Be<$n>;
260        }
261
262        impl AsBe for NonZero<$n> {
263            type Be = Nz<Be<$n>>;
264        }
265
266        impl NonZeroable for Le<$n> {
267            type Nz = NonZero<$n>;
268            fn to_nz(&self) -> Option<Self::Nz> {
269                NonZero::new(self.0)
270            }
271            fn from_nz(nz: &Self::Nz) -> Self {
272                Self(nz.get())
273            }
274        }
275
276        impl NonZeroable for Be<$n> {
277            type Nz = NonZero<$n>;
278            fn to_nz(&self) -> Option<Self::Nz> {
279                NonZero::new(self.0)
280            }
281            fn from_nz(nz: &Self::Nz) -> Self {
282                Self(nz.get())
283            }
284        }
285
286        impl From<NonZero<$n>> for Nz<Le<$n>> {
287            fn from(nz: NonZero<$n>) -> Self {
288                Self(nz)
289            }
290        }
291
292        impl From<NonZero<$n>> for Nz<Be<$n>> {
293            fn from(nz: NonZero<$n>) -> Self {
294                Self(nz)
295            }
296        }
297
298        impl ToOutput for Le<$n> {
299            fn to_output(&self, output: &mut dyn Output) {
300                output.write(&self.0.to_le_bytes());
301            }
302        }
303
304        impl ToOutput for Be<$n> {
305            fn to_output(&self, output: &mut dyn Output) {
306                output.write(&self.0.to_be_bytes());
307            }
308        }
309
310        impl<I: ParseInput> ParseInline<I> for Le<$n> {
311            fn parse_inline(input: &mut I) -> crate::Result<Self> {
312                Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
313            }
314        }
315
316        impl<I: ParseInput> ParseInline<I> for Be<$n> {
317            fn parse_inline(input: &mut I) -> crate::Result<Self> {
318                Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
319            }
320        }
321
322        impl Size for Le<$n> {
323            const SIZE: usize = std::mem::size_of::<$n>();
324            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
325        }
326
327        impl Size for Be<$n> {
328            const SIZE: usize = std::mem::size_of::<$n>();
329            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
330        }
331
332        impl MaybeHasNiche for Le<$n> {
333            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
334        }
335
336        impl MaybeHasNiche for Be<$n> {
337            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
338        }
339
340        impl Topological for Le<$n> {
341            fn accept_points(&self, _: &mut impl PointVisitor) {}
342        }
343
344        impl Topological for Be<$n> {
345            fn accept_points(&self, _: &mut impl PointVisitor) {}
346        }
347
348        impl Tagged for Le<$n> {}
349        impl Tagged for Be<$n> {}
350        impl ReflessObject for Le<$n> {}
351        impl ReflessObject for Be<$n> {}
352        impl ReflessInline for Le<$n> {}
353        impl ReflessInline for Be<$n> {}
354        impl Object for Le<$n> {}
355        impl Object for Be<$n> {}
356        impl Inline for Le<$n> {}
357        impl Inline for Be<$n> {}
358
359        impl Equivalent<Le<$n>> for Option<Le<NonZero<$n>>> {
360            fn into_equivalent(self) -> Le<$n> {
361                Le(self.map(|object| object.0.get()).unwrap_or_default())
362            }
363            fn from_equivalent(object: Le<$n>) -> Self {
364                NonZero::new(object.0).map(Le)
365            }
366        }
367
368        impl Equivalent<Be<$n>> for Option<Be<NonZero<$n>>> {
369            fn into_equivalent(self) -> Be<$n> {
370                Be(self.map(|object| object.0.get()).unwrap_or_default())
371            }
372            fn from_equivalent(object: Be<$n>) -> Self {
373                NonZero::new(object.0).map(Be)
374            }
375        }
376
377        impl Equivalent<Le<Os<$n>>> for Le<$n> {
378            fn into_equivalent(self) -> Le<Os<$n>> {
379                Le(self.0 as _)
380            }
381            fn from_equivalent(object: Le<Os<$n>>) -> Self {
382                Le(object.0 as _)
383            }
384        }
385
386        impl Equivalent<Be<Os<$n>>> for Be<$n> {
387            fn into_equivalent(self) -> Be<Os<$n>> {
388                Be(self.0 as _)
389            }
390            fn from_equivalent(object: Be<Os<$n>>) -> Self {
391                Be(object.0 as _)
392            }
393        }
394
395        impl Equivalent<Le<NonZero<Os<$n>>>> for Le<NonZero<$n>> {
396            fn into_equivalent(self) -> Le<NonZero<Os<$n>>> {
397                Le(NonZero::new(self.0.get() as _).unwrap())
398            }
399            fn from_equivalent(object: Le<NonZero<Os<$n>>>) -> Self {
400                Le(NonZero::new(object.0.get() as _).unwrap())
401            }
402        }
403
404        impl Equivalent<Be<NonZero<Os<$n>>>> for Be<NonZero<$n>> {
405            fn into_equivalent(self) -> Be<NonZero<Os<$n>>> {
406                Be(NonZero::new(self.0.get() as _).unwrap())
407            }
408            fn from_equivalent(object: Be<NonZero<Os<$n>>>) -> Self {
409                Be(NonZero::new(object.0.get() as _).unwrap())
410            }
411        }
412    };
413}
414
415signs!(u8, i8);
416signs!(u16, i16);
417signs!(u32, i32);
418signs!(u64, i64);
419signs!(u128, i128);
420
421ae!(u8);
422ae!(i8);
423
424lebe!(u16);
425lebe!(i16);
426
427lebe!(u32);
428lebe!(i32);
429
430lebe!(u64);
431lebe!(i64);
432
433lebe!(u128);
434lebe!(i128);
435
436impl<T: NonZeroable> Deref for Nz<T> {
437    type Target = T::Nz;
438
439    fn deref(&self) -> &Self::Target {
440        &self.0
441    }
442}
443
444impl<T: NonZeroable + ToOutput> ToOutput for Nz<T> {
445    fn to_output(&self, output: &mut dyn Output) {
446        T::from_nz(&self.0).to_output(output);
447    }
448}
449
450impl<T: NonZeroable + ParseInline<I>, I: ParseInput> ParseInline<I> for Nz<T> {
451    fn parse_inline(input: &mut I) -> crate::Result<Self> {
452        Ok(Self(T::parse_inline(input)?.to_nz().ok_or(Error::Zero)?))
453    }
454}
455
456impl<T: NonZeroable + Size> Size for Nz<T> {
457    type Size = T::Size;
458}
459
460impl<T: NonZeroable + Size> MaybeHasNiche for Nz<T> {
461    type MnArray = SomeNiche<ZeroNiche<T::Size>>;
462}
463
464impl<T: NonZeroable> Topological for Nz<T> {
465    fn accept_points(&self, _: &mut impl PointVisitor) {}
466}
467
468impl<T: NonZeroable> Tagged for Nz<T> {}
469impl<T: NonZeroable + ReflessInline> ReflessObject for Nz<T> {}
470impl<T: NonZeroable + ReflessInline> ReflessInline for Nz<T> {}
471impl<T: NonZeroable + Inline> Object for Nz<T> {}
472impl<T: NonZeroable + Inline> Inline for Nz<T> {}
473
474#[test]
475fn nonzero() {
476    assert_eq!(Option::<Ae<u8>>::SIZE, 2);
477    assert_eq!(Option::<Nz<Ae<u8>>>::SIZE, 1);
478    assert_eq!(Option::<Le<u16>>::SIZE, 3);
479    assert_eq!(Option::<Nz<Le<u16>>>::SIZE, 2);
480}