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}