heterob/
common.rs

1/*!
2# Type wrappers
3
4This module mostly defines type wrappers for primitive types. For example, tuple wrapper for arity equal to six named [T6].
5
6## Tuple wrappers
7
8These wrappers used to implement transformations using std trait [From].
9
10[T3] Example implementations:
11
12- [Splits one array to multiple arrays](struct.T3.html#impl-From<%5BT;+N%5D>-for-T3<%5BT;+AN%5D,+%5BT;+BN%5D,+%5BT;+CN%5D>)
13
14  `[T;N]` -> `[T; AN], [T; BN], [T; CN]` where `AN + BN + CN = N`
15
16  ```
17  # use heterob::T3;
18  let T3(a, b, c) = T3::from([0, 1, 1, 2, 2, 2]);
19  assert_eq!([0], a);
20  assert_eq!([1, 1], b);
21  assert_eq!([2, 2, 2], c);
22  ```
23
24- [Transforms from native tuple](struct.T3.html#impl-From<(A0,+B0,+C0)>-for-T3<A1,+B1,+C1>)
25
26  `(A0, B0, C0)` -> `T3(A1, B1, C1)` where A1, B1, C1 have [From] A0, B0, C0 traits respectively.
27  It could be useful for muliple value-to-value conversion.
28
29  ```
30  # use heterob::T3;
31  let T3(a, b, c) = T3::from(('a', 42u8, &"maybe"));
32  assert_eq!('a', a);
33  assert_eq!(42u32, b);
34  assert_eq!(Some(&"maybe"), c);
35  ```
36
37- [Transforms into native tuple](struct.T3.html#impl-From<T3<A0,+B0,+C0>>-for-(A1,+B1,+C1))
38
39  `T3(A0, B0, C0)` -> `(A1, B1, C1)` where A1, B1, C1 have [From] A0, B0, C0 traits respectively
40
41  ```
42  # use heterob::T3;
43  let (a, b, c): (_, u32, _) = T3('a', 42u8, &"maybe").into();
44  assert_eq!('a', a);
45  assert_eq!(42, b);
46  assert_eq!(Some(&"maybe"), c);
47  ```
48
49## Ready to partition value wrappers
50
51These wrappers used to show how value could be partitioned
52
53It is useful to reduce records length of same type tuple wrappers:
54`T3<[u16; 1], [u16; 2], [u16; 3]>` equals to `P3<u16, 1, 2, 3>`
55
56[P3] Example implementations:
57
58- [Transforms array to tuple of types](struct.P3.html#impl-From<P3<%5BTY;+NU%5D,+AN,+BN,+CN>>-for-(A,+B,+C))
59
60  `[T; N]` -> `(A, B, C)` where A, B, C have [From] `[T; AN]`, `[T; BN]`, `[T; CN]` traits respectively
61
62  ```
63  # use heterob::{P3, T1};
64  let (a, b, c): ([_; 1], _, _) = P3::<_, 1, 2, 3>([0, 1, 1, 2, 2, 2]).into();
65  assert_eq!([0], a);
66  assert_eq!((1, 1), b);
67  assert_eq!(T1([2, 2, 2]), c);
68  ```
69
70- [Try to transform slice to tuple of types](struct.P3.html#impl-TryFrom<P3<%26%5BT%5D,+AN,+BN,+CN>>-for-Seq<U,+%26%5BT%5D>)
71
72  `&[N]` -> `(A, B, C)` where A, B, C have [From] `[T; AN]`, `[T; BN]`, `[T; CN]` traits respectively
73
74  ```
75  # use heterob::{Seq, T3, P3};
76  let seq = P3([0, 1, 1, 2, 2, 2, 42].as_slice()).try_into().unwrap();
77  assert_eq!(Seq { head: ([0], [1, 1], [2, 2, 2]), tail: [42].as_slice() }, seq);
78  ```
79
80## Byte or Bits sequences
81- [Splits sequnce into a head and a tail](Seq)
82
83  `[1, 2, 3, 4, 5]` -> `Seq { head: [1, 2], tail: [3, 4, 5] }`
84
85  ```
86  # use heterob::Seq;
87  let seq = ['a', 'b', 'c'].as_slice().try_into().unwrap();
88  assert_eq!(Seq { head: ['a', 'b'], tail: ['c'].as_slice() }, seq);
89  ```
90
91## Type coercion wrappers
92- [Coerce arbitrary type to primitive](struct.U16.html)
93
94  `U16<ArbitraryType>` -> `u16` where `ArbitraryType` has `From<u16>` implementation
95
96  Instead of using `From::<u16>::from(value)` we could use just `U16(field)`
97
98  ```
99  # use heterob::{P2, U16, U32, U64, endianness::BeBytesInto};
100  let P2((a, U16(b))): P2<_, 2, 2> = [0, 0, 1, 1].be_bytes_into();
101  // The `a` should be exact 2 bytes long (u16)
102  let _: u64 = From::<u16>::from(a);
103  // Or U16 wrapper above
104  let _: u64 = b;
105  ```
106*/
107
108use core::array::TryFromSliceError;
109
110use funty::Fundamental;
111use paste::paste;
112
113/// Trait derives primitive types.
114///
115/// 'Opposite' to [funty::Fundamental](https://docs.rs/funty/latest/funty/trait.Fundamental.html)
116/// trait
117pub trait AsPrimitive<T> {
118    #[allow(clippy::wrong_self_convention)]
119    fn as_primitive(self) -> T;
120}
121impl<T: Fundamental> AsPrimitive<Option<char>> for T {
122    fn as_primitive(self) -> Option<char> {
123        self.as_char()
124    }
125}
126
127/// Reserved space unit type implementation
128impl<T> AsPrimitive<()> for T {
129    fn as_primitive(self) {}
130}
131
132macro_rules! main_impl_for {
133    ( AsPrimitive => $($cl:ty),+ $(,)?) => {paste!{ $(
134        impl<T: Fundamental> AsPrimitive<$cl> for T {
135            fn as_primitive(self) -> $cl { self.[<as_ $cl>]() }
136        }
137    )+ }};
138}
139
140main_impl_for!(AsPrimitive => bool,u8,u16,u32,u64,u128,usize);
141
142/// Sequence of elements with head and tail
143#[derive(Debug, Clone, PartialEq, Eq)]
144pub struct Seq<H, T> {
145    pub head: H,
146    pub tail: T,
147}
148
149/**
150Fallible conversion from slice to array
151
152In contrast with std
153[`TryFrom<&'_ [T]> for [T; N]`](https://doc.rust-lang.org/std/primitive.array.html#impl-TryFrom%3C%26%27_%20%5BT%5D%3E)
154this implementation return array and slice tail on any slice that longer than array
155```rust
156# use heterob::Seq;
157let bytes = [1u8, 2, 2, 3, 3, 3, 3];
158let seq: Seq<[_; 3], _> = bytes[..].try_into().unwrap();
159assert_eq!(Seq { head: [1, 2, 2], tail: [3, 3, 3, 3].as_slice() }, seq);
160```
161*/
162
163impl<'a, T, const N: usize> TryFrom<&'a [T]> for Seq<[T; N], &'a [T]>
164where
165    T: Copy,
166{
167    type Error = TryFromSliceError;
168
169    fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
170        let (head, tail) = slice.split_at(slice.len().min(N));
171        Ok(Self {
172            head: head.try_into()?,
173            tail,
174        })
175    }
176}
177
178macro_rules! common_impl {
179    ($len:expr; $_:ident $(,)? $($cl:ident),* $(,)?) => { paste!{
180        // #[derive(Debug, Clone, PartialEq, Eq)]
181        // pub struct T3<A, B, C>(pub A, pub B, pub C);
182        #[doc=concat!($len, "-ary tuple wrapper")]
183        #[derive(Debug, Clone, PartialEq, Eq)]
184        pub struct [<T $len>]<A, $($cl, )*>(pub A, $(pub $cl, )*);
185
186        /*
187        impl<A0, A1, B0, B1, C0, C1> From<T3<A0, B0, C0>> for (A1, B1, C1)
188        where
189            A1: From<A0>,
190            B1: From<B0>,
191            C1: From<C0>,
192        {
193            fn from(T3(a, b, c): T3<A0, B0, C0>) -> Self {
194                (a.into(), b.into(), c.into())
195            }
196        }
197        */
198        impl<A0, A1, $([<$cl 0>], [<$cl 1>], )*> From<[<T $len>]<A0, $([<$cl 0>], )*>> for (A1, $([<$cl 1>], )*)
199        where
200            A1: From<A0>, $([<$cl 1>]: From<[<$cl 0>]>, )*
201        {
202            fn from([<T $len>](a, $([<$cl:lower>], )*): [<T $len>]<A0, $([<$cl 0>], )*>) -> Self {
203                (a.into(), $([<$cl:lower>].into(), )*)
204            }
205        }
206
207        /*
208        impl<A0, A1, B0, B1, C0, C1> From<(A0, B0, C0)> for T3<A1, B1, C1>
209        where
210            A1: From<A0>,
211            B1: From<B0>,
212            C1: From<C0>,
213        {
214            fn from((a, b, c): (A0, B0, C0)) -> Self {
215                T3(a.into(), b.into(), c.into())
216            }
217        }
218        */
219        impl<A0, A1, $([<$cl 0>], [<$cl 1>], )*> From<(A0, $([<$cl 0>], )*)> for [<T $len>]<A1, $([<$cl 1>], )*>
220        where
221            A1: From<A0>, $([<$cl 1>]: From<[<$cl 0>]>, )*
222        {
223            fn from((a, $([<$cl:lower>], )*): (A0, $([<$cl 0>], )*)) -> Self {
224                Self(a.into(), $([<$cl:lower>].into(), )*)
225            }
226        }
227
228        /*
229        impl<T, const N: usize, const AN: usize, const BN: usize, const CN: usize>
230            From<[T; N]> for T3<[T; AN], [T; BN], [T; CN]>
231        where
232            T: Default + Copy,
233        {
234            fn from(data: [T; N]) -> Self {
235                const {
236                    const MSG: &str =
237                        concat!("The sum ", stringify!(AN $(+ [<$cl N>])*), " should be equal to N");
238                     assert!(AN $(+ [<$cl N>])* == N, "{}", MSG);
239                }
240
241                let end = 0;
242
243                let mut a = [Default::default(); AN];
244                let (start, end) = (end, end + AN);
245                a.copy_from_slice(&data[start..end]);
246
247                let mut b = [Default::default(); BN];
248                let (start, end) = (end, end + BN);
249                b.copy_from_slice(&data[start..end]);
250
251                let mut c = [Default::default(); CN];
252                let (start, end) = (end, end + CN);
253                c.copy_from_slice(&data[start..end]);
254
255                T3(a, b, c)
256            }
257        }
258        */
259        impl<T, const N: usize, const AN: usize, $(const [<$cl N>]: usize, )*>
260            From<[T; N]> for [<T $len>]<[T; AN], $([T; [<$cl N>]],)*>
261        where
262            T: Default + Copy,
263        {
264            fn from(data: [T; N]) -> Self {
265                const {
266                    const MSG: &str =
267                        concat!("The sum ", stringify!(AN $(+ [<$cl N>])*), " should be equal to N");
268                     assert!(AN $(+ [<$cl N>])* == N, "{}", MSG);
269                }
270
271                let end = 0;
272
273                let mut a = [Default::default(); AN];
274                let (start, end) = (end, end + AN);
275                a.copy_from_slice(&data[start..end]);
276
277                $(
278                    let mut [<$cl:lower>] = [Default::default();[<$cl N>]];
279                    let (start, end) = (end, end + [<$cl N>]);
280                    [<$cl:lower>].copy_from_slice(&data[start..end]);
281                )*
282                Self(a, $([<$cl:lower>], )*)
283            }
284        }
285
286        // #[derive(Debug, Clone, PartialEq, Eq)]
287        // pub struct P3<TY, const A: usize, const B: usize, const C: usize>(pub TY);
288        #[doc=concat!("Type wrapper with ", $len, " const generic parameters")]
289        #[derive(Debug, Clone, PartialEq, Eq)]
290        pub struct [<P $len>]<TY, const A: usize, $(const $cl: usize, )*>(pub TY);
291        // impl<TY, const AN: usize, const BN: usize, const CN: usize> P3<TY, AN, BN, CN> {
292        //     pub const SUM: usize = AN + BN + CN;
293        // }
294        impl<TY, const AN: usize, $(const [<$cl N>]: usize, )*> [<P $len>]<TY, AN, $([<$cl N>], )*> {
295            pub const SUM: usize = AN $(+ [<$cl N>])*;
296        }
297
298        /*
299        impl<TY,A,B,C, const N: usize, const AN: usize, const BN: usize, const CN: usize>
300            From<P3<[TY;N],AN,BN,CN>> for (A,B,C,)
301        where
302            TY: Copy + Default,
303            A: From<[TY;AN]>,
304            B: From<[TY;BN]>,
305            C: From<[TY;CN]>,
306        {
307            fn from(P3(data): P3<[TY;N],AN,BN,CN>) -> Self {
308                T3::from(data).into()
309            }
310        }
311        */
312        impl<TY, A, $($cl, )* const NU: usize, const AN: usize, $(const [<$cl N>]: usize, )*>
313            From<[<P $len>]<[TY; NU], AN, $([<$cl N>], )*>> for (A, $($cl, )*)
314        where
315            TY: Copy + Default,
316            A: From<[TY; AN]>, $($cl: From<[TY;[<$cl N>]]>, )*
317        {
318            fn from([<P $len>](data): [<P $len>]<[TY; NU], AN, $([<$cl N>], )*>) -> Self {
319                [<T $len>]::from(data).into()
320            }
321        }
322
323        /*
324        impl<'a, T, const AN: usize, const BN: usize, const CN: usize> TryFrom<&'a [T]>
325            for Seq<T3<[T; AN], [T; BN], [T; CN]>, &'a [T]>
326        where
327            T: Copy,
328        {
329            type Error = TryFromSliceError;
330
331            fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
332                let Seq { head: a, tail: slice }: Seq<_, &[T]> = slice.try_into()?;
333                let Seq { head: b, tail: slice }: Seq<_, &[T]> = slice.try_into()?;
334                let Seq { head: c, tail: slice }: Seq<_, &[T]> = slice.try_into()?;
335                Ok(Self {
336                    head: T3(a, b, c),
337                    tail: slice,
338                })
339            }
340        }
341        */
342        impl<'a, T, const AN: usize, $(const [<$cl N>]: usize, )*> TryFrom<&'a [T]>
343            for Seq<[<T $len>]<[T; AN], $([T; [<$cl N>]], )*>, &'a [T]>
344        where
345            T: Copy,
346        {
347            type Error = TryFromSliceError;
348
349            fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
350                let Seq { head: a, tail: slice }: Seq<_, &[T]> = slice.try_into()?;
351                $(
352                    let Seq { head: [<$cl:lower>], tail: slice }: Seq<_, &[T]> =
353                        slice.try_into()?;
354                )*
355                Ok(Self {
356                    head: [<T $len>](a, $([<$cl:lower>], )*),
357                    tail: slice,
358                })
359            }
360        }
361
362        /*
363        impl<'a, T, U, const AN: usize, const BN: usize, const CN: usize>
364            TryFrom<P3<&'a [T], AN, BN, CN>> for Seq<U, &'a [T]>
365        where
366            T: Copy,
367            U: From<T3<[T; AN], [T; BN], [T; CN]>>,
368        {
369            type Error = TryFromSliceError;
370
371            fn try_from(P3(data): P3<&'a [T], AN, BN, CN>) -> Result<Self, Self::Error> {
372                data.try_into().map(|Seq { head, tail }| Seq {
373                    head: From::<T3<[T; AN], [T; BN], [T; CN]>>::from(head),
374                    tail,
375                })
376            }
377        }
378        */
379        impl<'a, T, U, const AN: usize, $(const [<$cl N>]: usize, )*>
380            TryFrom<[<P $len>]<&'a [T], AN, $([<$cl N>], )*>> for Seq<U, &'a [T]>
381        where
382            T: Copy,
383            U: From<[<T $len>]<[T; AN], $([T;[<$cl N>]], )*>>
384        {
385            type Error = TryFromSliceError;
386
387            fn try_from([<P $len>](data): [<P $len>]<&'a [T], AN, $([<$cl N>], )*>) ->
388                 Result<Self, Self::Error>
389            {
390                data.try_into().map(|Seq { head,  tail }| Seq {
391                    head: From::<[<T $len>]<[T; AN], $([T; [<$cl N>]], )*>>::from(head),
392                    tail,
393                })
394            }
395        }
396    }};
397}
398
399// Monuple
400common_impl!(1; A);
401// Couple
402common_impl!(2; A,B);
403// Triple
404common_impl!(3; A,B,C);
405// Quadruple
406common_impl!(4; A,B,C,D);
407// Quintuple
408common_impl!(5; A,B,C,D,E);
409// Sextuple
410common_impl!(6; A,B,C,D,E,F);
411// Septuple
412common_impl!(7; A,B,C,D,E,F,G);
413// Octuple
414common_impl!(8; A,B,C,D,E,F,G,H);
415// Nonuple
416common_impl!(9; A,B,C,D,E,F,G,H,I);
417// Decuple
418common_impl!(10; A,B,C,D,E,F,G,H,I,J);
419// Undecuple
420common_impl!(11; A,B,C,D,E,F,G,H,I,J,K);
421// Duodecuple
422common_impl!(12; A,B,C,D,E,F,G,H,I,J,K,L);
423// Tredecuple
424common_impl!(13; A,B,C,D,E,F,G,H,I,J,K,L,M);
425// Quattuordecuple
426common_impl!(14; A,B,C,D,E,F,G,H,I,J,K,L,M,N);
427// Quindecuple
428common_impl!(15; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O);
429// Sexdecuple
430common_impl!(16; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P);
431// Septendecuple
432common_impl!(17; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q);
433// Octodecuple
434common_impl!(18; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R);
435// Novemdecuple
436common_impl!(19; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S);
437// Vigintuple
438common_impl!(20; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T);
439// Unvigintuple
440common_impl!(21; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U);
441// Duovigintuple
442common_impl!(22; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V);
443// Trevigintuple
444common_impl!(23; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W);
445// Quattuorvigintuple
446common_impl!(24; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X);
447// Quinvigintuple
448common_impl!(25; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y);
449// Sexvigintuple
450common_impl!(26; A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z);
451
452// #[derive(Debug, Clone, PartialEq, Eq)]
453// pub struct U8<T>(T);
454
455// impl<T: From<u8>, U: Fundamental> AsPrimitive<U8<T>> for U {
456//     fn as_primitive(self) -> U8<T> {
457//         U8(self.as_u8().into())
458//     }
459// }
460
461macro_rules! impl_wrappers_as_primitive {
462    ($($ty:ty),+ $(,)?) => {paste!{ $(
463        #[doc=concat!("Wrapper around type that may be converted from [", stringify!([<$ty:lower>]), "]")]
464        #[derive(Debug, Clone, PartialEq, Eq)]
465        pub struct $ty<T: From<[<$ty:lower>]>>(pub T);
466
467        impl<T: From<[<$ty:lower>]>, U: Fundamental> AsPrimitive<$ty<T>> for U {
468            fn as_primitive(self) -> $ty<T> {
469                $ty(self.[<as_ $ty:lower>]().into())
470            }
471        }
472    )+ }};
473}
474
475impl_wrappers_as_primitive!(Bool, U8, U16, U32, U64, U128, Usize);
476
477#[cfg(test)]
478mod tests {
479    use super::*;
480
481    #[test]
482    fn split_array() {
483        let chars = ['a', 'b', 'b'];
484        assert_eq!(T2(['a'], ['b', 'b']), T2::from(chars));
485
486        let bytes = [1u8, 2, 2, 3, 3, 3, 3];
487        assert_eq!(T3([1], [2, 2], [3, 3, 3, 3]), T3::from(bytes));
488    }
489
490    #[test]
491    fn tuple_of_elements_from() {
492        assert_eq!((97u128, 98usize), T2(97u8, 98u16).into());
493        assert_eq!(('a', 'b', 'c'), T3(97, 98, 99).into());
494    }
495
496    #[test]
497    fn tuple_of_elements_into() {
498        assert_eq!(T2(97u32, 98i32), (97u8, 98u16).into());
499        assert_eq!(T3('a', 'b', 'c'), (97, 98, 99).into());
500    }
501
502    #[test]
503    fn slice_try_into_tuple_of_arrays() {
504        let bytes = [1u8, 2, 2, 3, 3, 3, 3];
505        let Seq {
506            head: T3(a, b, c), ..
507        } = bytes[..].try_into().unwrap();
508        assert_eq!(([1], [2, 2], [3, 3, 3]), (a, b, c));
509    }
510
511    #[test]
512    fn partition_ready_longer_slice_try_into() {
513        let bytes = [1u8, 2, 2, 3, 3, 3, 3, 42];
514
515        let result = bytes.as_slice().try_into().ok();
516        let sample = Some(Seq {
517            head: T3([1], [2, 2], [3, 3, 3, 3]),
518            tail: &bytes[7..],
519        });
520        assert_eq!(sample, result, "tuple warpper");
521
522        let result = P3(bytes.as_slice()).try_into().ok();
523        let sample = Some(Seq {
524            head: ([1], [2, 2], [3, 3, 3, 3]),
525            tail: &bytes[7..],
526        });
527        assert_eq!(sample, result, "tuple of arrays");
528    }
529
530    #[test]
531    fn partition_ready_exact_slice_try_into() {
532        let bytes = [1u8, 2, 2, 3, 3, 3, 3];
533
534        let result = bytes.as_slice().try_into().ok();
535        let sample = Some(Seq {
536            head: T3([1], [2, 2], [3, 3, 3, 3]),
537            tail: [].as_slice(),
538        });
539        assert_eq!(sample, result, "tuple warpper");
540
541        let result = P3(bytes.as_slice()).try_into().ok();
542        let sample = Some(Seq {
543            head: ([1], [2, 2], [3, 3, 3, 3]),
544            tail: [].as_slice(),
545        });
546        assert_eq!(sample, result, "tuple of arrays");
547    }
548
549    #[test]
550    fn partition_ready_shorter_slice_try_into() {
551        let bytes = [1u8, 2, 2, 3, 3];
552
553        #[allow(clippy::type_complexity)]
554        let result: Option<Seq<T3<[_; 1], [_; 2], [_; 3]>, &[u8]>> =
555            bytes.as_slice().try_into().ok();
556        let sample = None;
557        assert_eq!(sample, result, "slice is shorter");
558
559        #[allow(clippy::type_complexity)]
560        let result: Option<Seq<([_; 1], [_; 2], [_; 3]), &[u8]>> =
561            P3(bytes.as_slice()).try_into().ok();
562        let sample = None;
563        assert_eq!(sample, result, "slice is shorter");
564    }
565
566    #[test]
567    fn const_generic_params_sum() {
568        assert_eq!(6, P3::<u8, 1, 2, 3>::SUM);
569    }
570
571    #[test]
572    fn wrappers_as_primitives() {
573        #[derive(Debug, Clone, PartialEq, Eq)]
574        enum En {
575            One,
576        }
577        impl From<u8> for En {
578            fn from(_: u8) -> Self {
579                Self::One
580            }
581        }
582        assert_eq!(U8(En::One), 0u8.as_primitive());
583        assert_eq!(U8(En::One), 0u16.as_primitive());
584        assert_eq!(U8(En::One), 0u32.as_primitive());
585        assert_eq!(U8(En::One), 0u64.as_primitive());
586        assert_eq!(U8(En::One), 0u128.as_primitive());
587        assert_eq!(U8(En::One), 0usize.as_primitive());
588        assert_eq!(U8(En::One), false.as_primitive());
589    }
590}