Skip to main content

object_rainbow/numeric/
private.rs

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