Skip to main content

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, Debug)]
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, Debug)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct Be<T>(pub T);
17
18impl<T> Le<T> {
19    pub const fn new(value: T) -> Self {
20        Self(value)
21    }
22}
23
24impl<T> Be<T> {
25    pub const fn new(value: T) -> Self {
26        Self(value)
27    }
28}
29
30impl<T> From<T> for Be<T> {
31    fn from(n: T) -> Self {
32        Self(n)
33    }
34}
35
36impl<T> From<T> for Le<T> {
37    fn from(n: T) -> Self {
38        Self(n)
39    }
40}
41
42impl<T> Deref for Le<T> {
43    type Target = T;
44
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50impl<T> Deref for Be<T> {
51    type Target = T;
52
53    fn deref(&self) -> &Self::Target {
54        &self.0
55    }
56}
57
58pub trait AsLe {
59    type Le;
60    fn construct(self) -> Self::Le;
61}
62
63pub trait AsBe {
64    type Be;
65    fn construct(self) -> Self::Be;
66}
67
68macro_rules! signs {
69    ($u:ty, $i:ty) => {
70        impl HasOtherSign for $u {
71            type OtherSign = $i;
72        }
73        impl HasOtherSign for $i {
74            type OtherSign = $u;
75        }
76    };
77}
78
79macro_rules! ae {
80    ($n:ty) => {
81        impl UsizeTag for $n {
82            fn from_usize(n: usize) -> Self {
83                n.try_into().expect("discriminant out of range")
84            }
85            fn to_usize(&self) -> usize {
86                (*self).try_into().expect("discriminant out of range")
87            }
88            fn try_to_usize(&self) -> Option<usize> {
89                (*self).try_into().ok()
90            }
91        }
92
93        impl UsizeTag for NonZero<$n> {
94            fn from_usize(n: usize) -> Self {
95                Self::new(
96                    n.checked_add(1)
97                        .expect("discriminant out of range")
98                        .try_into()
99                        .expect("discriminant out of range"),
100                )
101                .unwrap()
102            }
103            fn to_usize(&self) -> usize {
104                usize::try_from(self.get())
105                    .expect("discriminant out of range")
106                    .checked_sub(1)
107                    .unwrap()
108            }
109            fn try_to_usize(&self) -> Option<usize> {
110                usize::try_from(self.get()).ok()?.checked_sub(1)
111            }
112        }
113
114        impl AsLe for $n {
115            type Le = Self;
116            fn construct(self) -> Self::Le {
117                self
118            }
119        }
120
121        impl AsLe for NonZero<$n> {
122            type Le = Self;
123            fn construct(self) -> Self::Le {
124                self
125            }
126        }
127
128        impl AsBe for $n {
129            type Be = Self;
130            fn construct(self) -> Self::Be {
131                self
132            }
133        }
134
135        impl AsBe for NonZero<$n> {
136            type Be = Self;
137            fn construct(self) -> Self::Be {
138                self
139            }
140        }
141
142        impl ToOutput for NonZero<$n> {
143            fn to_output(&self, output: &mut dyn crate::Output) {
144                self.get().to_output(output);
145            }
146        }
147
148        impl<I: ParseInput> Parse<I> for NonZero<$n> {
149            fn parse(input: I) -> crate::Result<Self> {
150                ParseInline::parse_as_inline(input)
151            }
152        }
153
154        impl<I: ParseInput> ParseInline<I> for NonZero<$n> {
155            fn parse_inline(input: &mut I) -> crate::Result<Self> {
156                NonZero::new(input.parse_inline::<$n>()?).ok_or(Error::Zero)
157            }
158        }
159
160        impl Size for NonZero<$n> {
161            const SIZE: usize = <$n as Size>::SIZE;
162            type Size = <$n as Size>::Size;
163        }
164
165        impl MaybeHasNiche for $n {
166            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
167        }
168
169        impl MaybeHasNiche for NonZero<$n> {
170            type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
171        }
172
173        impl Tagged for $n {}
174        impl Tagged for NonZero<$n> {}
175        impl ListHashes for $n {}
176        impl ListHashes for NonZero<$n> {}
177        impl Topological for $n {}
178        impl Topological for NonZero<$n> {}
179
180        impl Equivalent<$n> for Option<NonZero<$n>> {
181            fn into_equivalent(self) -> $n {
182                self.map(NonZero::get).unwrap_or_default()
183            }
184            fn from_equivalent(object: $n) -> Self {
185                NonZero::new(object)
186            }
187        }
188
189        impl Equivalent<Os<$n>> for $n {
190            fn into_equivalent(self) -> Os<$n> {
191                self as _
192            }
193            fn from_equivalent(object: Os<$n>) -> Self {
194                object as _
195            }
196        }
197
198        impl Equivalent<NonZero<Os<$n>>> for NonZero<$n> {
199            fn into_equivalent(self) -> NonZero<Os<$n>> {
200                NonZero::new(self.get() as _).unwrap()
201            }
202            fn from_equivalent(object: NonZero<Os<$n>>) -> Self {
203                NonZero::new(object.get() as _).unwrap()
204            }
205        }
206    };
207}
208
209macro_rules! lebe {
210    ($n:ty) => {
211        impl UsizeTag for $n {
212            fn from_usize(n: usize) -> Self {
213                n.try_into().expect("discriminant out of range")
214            }
215            fn to_usize(&self) -> usize {
216                (*self).try_into().expect("discriminant out of range")
217            }
218            fn try_to_usize(&self) -> Option<usize> {
219                (*self).try_into().ok()
220            }
221        }
222
223        impl UsizeTag for NonZero<$n> {
224            fn from_usize(n: usize) -> Self {
225                Self::new(
226                    n.checked_add(1)
227                        .expect("discriminant out of range")
228                        .try_into()
229                        .expect("discriminant out of range"),
230                )
231                .unwrap()
232            }
233            fn to_usize(&self) -> usize {
234                usize::try_from(self.get())
235                    .expect("discriminant out of range")
236                    .checked_sub(1)
237                    .unwrap()
238            }
239            fn try_to_usize(&self) -> Option<usize> {
240                usize::try_from(self.get()).ok()?.checked_sub(1)
241            }
242        }
243
244        impl AsLe for $n {
245            type Le = Le<$n>;
246            fn construct(self) -> Self::Le {
247                Le(self)
248            }
249        }
250
251        impl AsLe for NonZero<$n> {
252            type Le = Le<NonZero<$n>>;
253            fn construct(self) -> Self::Le {
254                Le(self)
255            }
256        }
257
258        impl AsBe for $n {
259            type Be = Be<$n>;
260            fn construct(self) -> Self::Be {
261                Be(self)
262            }
263        }
264
265        impl AsBe for NonZero<$n> {
266            type Be = Be<NonZero<$n>>;
267            fn construct(self) -> Self::Be {
268                Be(self)
269            }
270        }
271
272        impl ToOutput for Le<$n> {
273            fn to_output(&self, output: &mut dyn Output) {
274                output.write(&self.0.to_le_bytes());
275            }
276        }
277
278        impl ToOutput for Be<$n> {
279            fn to_output(&self, output: &mut dyn Output) {
280                output.write(&self.0.to_be_bytes());
281            }
282        }
283
284        impl ToOutput for Le<NonZero<$n>> {
285            fn to_output(&self, output: &mut dyn Output) {
286                output.write(&self.0.get().to_le_bytes());
287            }
288        }
289
290        impl ToOutput for Be<NonZero<$n>> {
291            fn to_output(&self, output: &mut dyn Output) {
292                output.write(&self.0.get().to_be_bytes());
293            }
294        }
295
296        impl InlineOutput for Le<$n> {}
297        impl InlineOutput for Be<$n> {}
298
299        impl<I: ParseInput> ParseInline<I> for Le<$n> {
300            fn parse_inline(input: &mut I) -> crate::Result<Self> {
301                Ok(Self(<$n>::from_le_bytes(*input.parse_chunk()?)))
302            }
303        }
304
305        impl<I: ParseInput> ParseInline<I> for Be<$n> {
306            fn parse_inline(input: &mut I) -> crate::Result<Self> {
307                Ok(Self(<$n>::from_be_bytes(*input.parse_chunk()?)))
308            }
309        }
310
311        impl<I: ParseInput> ParseInline<I> for Le<NonZero<$n>> {
312            fn parse_inline(input: &mut I) -> crate::Result<Self> {
313                NonZero::new(input.parse_inline::<Le<$n>>()?.0)
314                    .ok_or(Error::Zero)
315                    .map(Le)
316            }
317        }
318
319        impl<I: ParseInput> ParseInline<I> for Be<NonZero<$n>> {
320            fn parse_inline(input: &mut I) -> crate::Result<Self> {
321                NonZero::new(input.parse_inline::<Be<$n>>()?.0)
322                    .ok_or(Error::Zero)
323                    .map(Be)
324            }
325        }
326
327        impl Size for Le<$n> {
328            const SIZE: usize = std::mem::size_of::<$n>();
329            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
330        }
331
332        impl Size for Be<$n> {
333            const SIZE: usize = std::mem::size_of::<$n>();
334            type Size = typenum::generic_const_mappings::U<{ Self::SIZE }>;
335        }
336
337        impl MaybeHasNiche for Le<$n> {
338            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
339        }
340
341        impl MaybeHasNiche for Be<$n> {
342            type MnArray = NoNiche<ZeroNoNiche<<Self as Size>::Size>>;
343        }
344
345        impl MaybeHasNiche for Le<NonZero<$n>> {
346            type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
347        }
348
349        impl MaybeHasNiche for Be<NonZero<$n>> {
350            type MnArray = SomeNiche<ZeroNiche<<Self as Size>::Size>>;
351        }
352
353        impl Tagged for Le<$n> {}
354        impl Tagged for Le<NonZero<$n>> {}
355        impl Tagged for Be<$n> {}
356        impl Tagged for Be<NonZero<$n>> {}
357        impl ListHashes for Le<$n> {}
358        impl ListHashes for Le<NonZero<$n>> {}
359        impl ListHashes for Be<$n> {}
360        impl ListHashes for Be<NonZero<$n>> {}
361        impl Topological for Le<$n> {}
362        impl Topological for Le<NonZero<$n>> {}
363        impl Topological for Be<$n> {}
364        impl Topological for Be<NonZero<$n>> {}
365
366        impl Size for Le<NonZero<$n>> {
367            const SIZE: usize = <Le<$n> as Size>::SIZE;
368            type Size = <Le<$n> as Size>::Size;
369        }
370
371        impl Size for Be<NonZero<$n>> {
372            const SIZE: usize = <Be<$n> as Size>::SIZE;
373            type Size = <Be<$n> as Size>::Size;
374        }
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
526#[test]
527fn nonzero() {
528    assert_eq!(Option::<super::Le<u8>>::SIZE, 2);
529    assert_eq!(Option::<super::Le<NonZero<u8>>>::SIZE, 1);
530    assert_eq!(Option::<super::Le<u16>>::SIZE, 3);
531    assert_eq!(Option::<super::Le<NonZero<u16>>>::SIZE, 2);
532}
533
534impl<T: UsizeTag> UsizeTag for Le<T> {
535    fn from_usize(n: usize) -> Self {
536        Self(UsizeTag::from_usize(n))
537    }
538
539    fn to_usize(&self) -> usize {
540        self.0.to_usize()
541    }
542
543    fn try_to_usize(&self) -> Option<usize> {
544        self.0.try_to_usize()
545    }
546}
547
548impl<T: UsizeTag> UsizeTag for Be<T> {
549    fn from_usize(n: usize) -> Self {
550        Self(UsizeTag::from_usize(n))
551    }
552
553    fn to_usize(&self) -> usize {
554        self.0.to_usize()
555    }
556
557    fn try_to_usize(&self) -> Option<usize> {
558        self.0.try_to_usize()
559    }
560}