1
use crate::ByteConversionError;
2
use core::fmt::{Debug, Display, Formatter};
3
#[cfg(feature = "serde")]
4
use serde::{Deserialize, Serialize};
5
#[cfg(feature = "std")]
6
use std::error::Error;
7

            
8
pub trait ToBeBytes {
9
    type ByteArray: AsRef<[u8]>;
10
    /// Length when written to big endian bytes.
11
    fn written_len(&self) -> usize;
12
    fn to_be_bytes(&self) -> Self::ByteArray;
13
}
14

            
15
impl ToBeBytes for () {
16
    type ByteArray = [u8; 0];
17

            
18
    #[inline]
19
    fn written_len(&self) -> usize {
20
        0
21
    }
22

            
23
    #[inline]
24
    fn to_be_bytes(&self) -> Self::ByteArray {
25
        []
26
    }
27
}
28

            
29
impl ToBeBytes for u8 {
30
    type ByteArray = [u8; 1];
31

            
32
    #[inline]
33
1070
    fn written_len(&self) -> usize {
34
1070
        1
35
1070
    }
36

            
37
    #[inline]
38
356
    fn to_be_bytes(&self) -> Self::ByteArray {
39
356
        u8::to_be_bytes(*self)
40
356
    }
41
}
42

            
43
impl ToBeBytes for u16 {
44
    type ByteArray = [u8; 2];
45

            
46
    #[inline]
47
118
    fn written_len(&self) -> usize {
48
118
        2
49
118
    }
50

            
51
    #[inline]
52
36
    fn to_be_bytes(&self) -> Self::ByteArray {
53
36
        u16::to_be_bytes(*self)
54
36
    }
55
}
56

            
57
impl ToBeBytes for u32 {
58
    type ByteArray = [u8; 4];
59

            
60
    #[inline]
61
34
    fn written_len(&self) -> usize {
62
34
        4
63
34
    }
64

            
65
    #[inline]
66
8
    fn to_be_bytes(&self) -> Self::ByteArray {
67
8
        u32::to_be_bytes(*self)
68
8
    }
69
}
70

            
71
impl ToBeBytes for u64 {
72
    type ByteArray = [u8; 8];
73

            
74
    #[inline]
75
26
    fn written_len(&self) -> usize {
76
26
        8
77
26
    }
78

            
79
    #[inline]
80
8
    fn to_be_bytes(&self) -> Self::ByteArray {
81
8
        u64::to_be_bytes(*self)
82
8
    }
83
}
84

            
85
pub trait UnsignedEnum {
86
    /// Size of the unsigned enumeration in bytes.
87
    fn size(&self) -> usize;
88
    /// Write the unsigned enumeration to a raw buffer. Returns the written size on success.
89
    fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
90

            
91
    fn value(&self) -> u64;
92

            
93
    #[cfg(feature = "alloc")]
94
8
    fn to_vec(&self) -> alloc::vec::Vec<u8> {
95
8
        let mut buf = alloc::vec![0; self.size()];
96
8
        self.write_to_be_bytes(&mut buf).unwrap();
97
8
        buf
98
8
    }
99
}
100

            
101
pub trait UnsignedEnumExt: UnsignedEnum + Debug + Copy + Clone + PartialEq + Eq {}
102

            
103
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
104
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
105
pub enum UnsignedByteFieldError {
106
    /// Value is too large for specified width of byte field.
107
    ValueTooLargeForWidth {
108
        width: usize,
109
        value: u64,
110
    },
111
    /// Only 1, 2, 4 and 8 are allow width values. Optionally contains the expected width if
112
    /// applicable, for example for conversions.
113
    InvalidWidth {
114
        found: usize,
115
        expected: Option<usize>,
116
    },
117
    ByteConversionError(ByteConversionError),
118
}
119

            
120
impl From<ByteConversionError> for UnsignedByteFieldError {
121
    #[inline]
122
2
    fn from(value: ByteConversionError) -> Self {
123
2
        Self::ByteConversionError(value)
124
2
    }
125
}
126

            
127
impl Display for UnsignedByteFieldError {
128
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
129
        match self {
130
            Self::ByteConversionError(e) => {
131
                write!(f, "low level byte conversion error: {e}")
132
            }
133
            Self::InvalidWidth { found, .. } => {
134
                write!(f, "invalid width {found}, only 1, 2, 4 and 8 are allowed.")
135
            }
136
            Self::ValueTooLargeForWidth { width, value } => {
137
                write!(f, "value {value} too large for width {width}")
138
            }
139
        }
140
    }
141
}
142

            
143
#[cfg(feature = "std")]
144
impl Error for UnsignedByteFieldError {}
145

            
146
/// Type erased variant.
147
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
148
24
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
149
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
150
pub struct UnsignedByteField {
151
    width: usize,
152
    value: u64,
153
}
154

            
155
impl UnsignedByteField {
156
    #[inline]
157
844
    pub const fn new(width: usize, value: u64) -> Self {
158
844
        Self { width, value }
159
844
    }
160

            
161
    #[inline]
162
424
    pub const fn value_const(&self) -> u64 {
163
424
        self.value
164
424
    }
165

            
166
    #[inline]
167
226
    pub fn new_from_be_bytes(width: usize, buf: &[u8]) -> Result<Self, UnsignedByteFieldError> {
168
226
        if width > buf.len() {
169
2
            return Err(ByteConversionError::FromSliceTooSmall {
170
2
                expected: width,
171
2
                found: buf.len(),
172
2
            }
173
2
            .into());
174
224
        }
175
224
        match width {
176
            0 => Ok(Self::new(width, 0)),
177
204
            1 => Ok(Self::new(width, buf[0] as u64)),
178
16
            2 => Ok(Self::new(
179
16
                width,
180
16
                u16::from_be_bytes(buf[0..2].try_into().unwrap()) as u64,
181
16
            )),
182
2
            4 => Ok(Self::new(
183
2
                width,
184
2
                u32::from_be_bytes(buf[0..4].try_into().unwrap()) as u64,
185
2
            )),
186
2
            8 => Ok(Self::new(
187
2
                width,
188
2
                u64::from_be_bytes(buf[0..8].try_into().unwrap()),
189
2
            )),
190
            _ => Err(UnsignedByteFieldError::InvalidWidth {
191
                found: width,
192
                expected: None,
193
            }),
194
        }
195
226
    }
196
}
197

            
198
impl UnsignedEnum for UnsignedByteField {
199
    #[inline]
200
4484
    fn size(&self) -> usize {
201
4484
        self.width
202
4484
    }
203

            
204
    #[inline]
205
424
    fn value(&self) -> u64 {
206
424
        self.value_const()
207
424
    }
208

            
209
374
    fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
210
374
        if buf.len() < self.size() {
211
2
            return Err(ByteConversionError::ToSliceTooSmall {
212
2
                expected: self.size(),
213
2
                found: buf.len(),
214
2
            });
215
372
        }
216
372
        match self.size() {
217
            0 => Ok(0),
218
            1 => {
219
338
                let u8 = UnsignedByteFieldU8::try_from(*self).unwrap();
220
338
                u8.write_to_be_bytes(buf)
221
            }
222
            2 => {
223
30
                let u16 = UnsignedByteFieldU16::try_from(*self).unwrap();
224
30
                u16.write_to_be_bytes(buf)
225
            }
226
            4 => {
227
2
                let u32 = UnsignedByteFieldU32::try_from(*self).unwrap();
228
2
                u32.write_to_be_bytes(buf)
229
            }
230
            8 => {
231
2
                let u64 = UnsignedByteFieldU64::try_from(*self).unwrap();
232
2
                u64.write_to_be_bytes(buf)
233
            }
234
            _ => {
235
                // The API does not allow this.
236
                panic!("unexpected written length");
237
            }
238
        }
239
374
    }
240
}
241

            
242
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
243
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
244
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
245
pub struct GenericUnsignedByteField<TYPE: Copy + Into<u64>> {
246
    value: TYPE,
247
}
248

            
249
impl<TYPE: Copy + Into<u64>> GenericUnsignedByteField<TYPE> {
250
564
    pub const fn new(val: TYPE) -> Self {
251
564
        Self { value: val }
252
564
    }
253

            
254
42
    pub const fn value_typed(&self) -> TYPE {
255
42
        self.value
256
42
    }
257
}
258

            
259
impl<TYPE: Copy + ToBeBytes + Into<u64>> UnsignedEnum for GenericUnsignedByteField<TYPE> {
260
    #[inline]
261
840
    fn size(&self) -> usize {
262
840
        self.value.written_len()
263
840
    }
264

            
265
416
    fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
266
416
        if buf.len() < self.size() {
267
8
            return Err(ByteConversionError::ToSliceTooSmall {
268
8
                found: buf.len(),
269
8
                expected: self.size(),
270
8
            });
271
408
        }
272
408
        buf[..self.size()].copy_from_slice(self.value.to_be_bytes().as_ref());
273
408
        Ok(self.value.written_len())
274
416
    }
275

            
276
    #[inline]
277
16
    fn value(&self) -> u64 {
278
16
        self.value_typed().into()
279
16
    }
280
}
281

            
282
pub type UnsignedByteFieldEmpty = GenericUnsignedByteField<()>;
283
pub type UnsignedByteFieldU8 = GenericUnsignedByteField<u8>;
284
pub type UnsignedByteFieldU16 = GenericUnsignedByteField<u16>;
285
pub type UnsignedByteFieldU32 = GenericUnsignedByteField<u32>;
286
pub type UnsignedByteFieldU64 = GenericUnsignedByteField<u64>;
287

            
288
pub type UbfU8 = UnsignedByteFieldU8;
289
pub type UbfU16 = UnsignedByteFieldU16;
290
pub type UbfU32 = UnsignedByteFieldU32;
291
pub type UbfU64 = UnsignedByteFieldU64;
292

            
293
impl From<UnsignedByteFieldU8> for UnsignedByteField {
294
548
    fn from(value: UnsignedByteFieldU8) -> Self {
295
548
        Self::new(1, value.value as u64)
296
548
    }
297
}
298

            
299
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU8 {
300
    type Error = UnsignedByteFieldError;
301

            
302
    #[inline]
303
342
    fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
304
342
        if value.width != 1 {
305
2
            return Err(UnsignedByteFieldError::InvalidWidth {
306
2
                found: value.width,
307
2
                expected: Some(1),
308
2
            });
309
340
        }
310
340
        Ok(Self::new(value.value as u8))
311
342
    }
312
}
313

            
314
impl From<UnsignedByteFieldU16> for UnsignedByteField {
315
    #[inline]
316
44
    fn from(value: UnsignedByteFieldU16) -> Self {
317
44
        Self::new(2, value.value as u64)
318
44
    }
319
}
320

            
321
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU16 {
322
    type Error = UnsignedByteFieldError;
323

            
324
    #[inline]
325
34
    fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
326
34
        if value.width != 2 {
327
2
            return Err(UnsignedByteFieldError::InvalidWidth {
328
2
                found: value.width,
329
2
                expected: Some(2),
330
2
            });
331
32
        }
332
32
        Ok(Self::new(value.value as u16))
333
34
    }
334
}
335

            
336
impl From<UnsignedByteFieldU32> for UnsignedByteField {
337
    #[inline]
338
2
    fn from(value: UnsignedByteFieldU32) -> Self {
339
2
        Self::new(4, value.value as u64)
340
2
    }
341
}
342

            
343
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU32 {
344
    type Error = UnsignedByteFieldError;
345

            
346
    #[inline]
347
6
    fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
348
6
        if value.width != 4 {
349
2
            return Err(UnsignedByteFieldError::InvalidWidth {
350
2
                found: value.width,
351
2
                expected: Some(4),
352
2
            });
353
4
        }
354
4
        Ok(Self::new(value.value as u32))
355
6
    }
356
}
357

            
358
impl From<UnsignedByteFieldU64> for UnsignedByteField {
359
    #[inline]
360
2
    fn from(value: UnsignedByteFieldU64) -> Self {
361
2
        Self::new(8, value.value)
362
2
    }
363
}
364

            
365
impl TryFrom<UnsignedByteField> for UnsignedByteFieldU64 {
366
    type Error = UnsignedByteFieldError;
367

            
368
    #[inline]
369
6
    fn try_from(value: UnsignedByteField) -> Result<Self, Self::Error> {
370
6
        if value.width != 8 {
371
2
            return Err(UnsignedByteFieldError::InvalidWidth {
372
2
                found: value.width,
373
2
                expected: Some(8),
374
2
            });
375
4
        }
376
4
        Ok(Self::new(value.value))
377
6
    }
378
}
379

            
380
#[cfg(test)]
381
pub mod tests {
382
    use crate::util::{
383
        UnsignedByteField, UnsignedByteFieldError, UnsignedByteFieldU16, UnsignedByteFieldU32,
384
        UnsignedByteFieldU64, UnsignedByteFieldU8, UnsignedEnum,
385
    };
386
    use crate::ByteConversionError;
387
    use std::format;
388

            
389
    #[test]
390
2
    fn test_simple_u8() {
391
2
        let u8 = UnsignedByteFieldU8::new(5);
392
2
        assert_eq!(u8.size(), 1);
393
2
        let mut buf: [u8; 8] = [0; 8];
394
2
        let len = u8
395
2
            .write_to_be_bytes(&mut buf)
396
2
            .expect("writing to raw buffer failed");
397
2
        assert_eq!(len, 1);
398
2
        assert_eq!(buf[0], 5);
399
14
        for val in buf.iter().skip(1) {
400
14
            assert_eq!(*val, 0);
401
        }
402
2
        assert_eq!(u8.value_typed(), 5);
403
2
        assert_eq!(u8.value(), 5);
404
2
    }
405

            
406
    #[test]
407
2
    fn test_simple_u16() {
408
2
        let u16 = UnsignedByteFieldU16::new(3823);
409
2
        assert_eq!(u16.size(), 2);
410
2
        let mut buf: [u8; 8] = [0; 8];
411
2
        let len = u16
412
2
            .write_to_be_bytes(&mut buf)
413
2
            .expect("writing to raw buffer failed");
414
2
        assert_eq!(len, 2);
415
2
        let raw_val = u16::from_be_bytes(buf[0..2].try_into().unwrap());
416
2
        assert_eq!(raw_val, 3823);
417
12
        for val in buf.iter().skip(2) {
418
12
            assert_eq!(*val, 0);
419
        }
420
2
        assert_eq!(u16.value_typed(), 3823);
421
2
        assert_eq!(u16.value(), 3823);
422
2
    }
423

            
424
    #[test]
425
2
    fn test_simple_u32() {
426
2
        let u32 = UnsignedByteFieldU32::new(80932);
427
2
        assert_eq!(u32.size(), 4);
428
2
        let mut buf: [u8; 8] = [0; 8];
429
2
        let len = u32
430
2
            .write_to_be_bytes(&mut buf)
431
2
            .expect("writing to raw buffer failed");
432
2
        assert_eq!(len, 4);
433
2
        let raw_val = u32::from_be_bytes(buf[0..4].try_into().unwrap());
434
2
        assert_eq!(raw_val, 80932);
435
9
        (4..8).for_each(|i| {
436
8
            assert_eq!(buf[i], 0);
437
9
        });
438
2
        assert_eq!(u32.value_typed(), 80932);
439
2
        assert_eq!(u32.value(), 80932);
440
2
    }
441

            
442
    #[test]
443
2
    fn test_simple_u64() {
444
2
        let u64 = UnsignedByteFieldU64::new(5999999);
445
2
        assert_eq!(u64.size(), 8);
446
2
        let mut buf: [u8; 8] = [0; 8];
447
2
        let len = u64
448
2
            .write_to_be_bytes(&mut buf)
449
2
            .expect("writing to raw buffer failed");
450
2
        assert_eq!(len, 8);
451
2
        let raw_val = u64::from_be_bytes(buf[0..8].try_into().unwrap());
452
2
        assert_eq!(raw_val, 5999999);
453
2
        assert_eq!(u64.value_typed(), 5999999);
454
2
        assert_eq!(u64.value(), 5999999);
455
2
    }
456

            
457
    #[test]
458
2
    fn conversions_u8() {
459
2
        let u8 = UnsignedByteFieldU8::new(5);
460
2
        let u8_type_erased = UnsignedByteField::from(u8);
461
2
        assert_eq!(u8_type_erased.width, 1);
462
2
        assert_eq!(u8_type_erased.value, 5);
463
2
        let u8_conv_back =
464
2
            UnsignedByteFieldU8::try_from(u8_type_erased).expect("conversion failed for u8");
465
2
        assert_eq!(u8, u8_conv_back);
466
2
        assert_eq!(u8_conv_back.value, 5);
467
2
    }
468

            
469
    #[test]
470
2
    fn conversion_u8_fails() {
471
2
        let field = UnsignedByteField::new(2, 60000);
472
2
        let conv_fails = UnsignedByteFieldU8::try_from(field);
473
2
        assert!(conv_fails.is_err());
474
2
        let err = conv_fails.unwrap_err();
475
2
        match err {
476
            UnsignedByteFieldError::InvalidWidth {
477
2
                found,
478
2
                expected: Some(expected),
479
2
            } => {
480
2
                assert_eq!(found, 2);
481
2
                assert_eq!(expected, 1);
482
            }
483
            _ => {
484
                panic!("{}", format!("invalid error {err}"))
485
            }
486
        }
487
2
    }
488

            
489
    #[test]
490
2
    fn conversions_u16() {
491
2
        let u16 = UnsignedByteFieldU16::new(64444);
492
2
        let u16_type_erased = UnsignedByteField::from(u16);
493
2
        assert_eq!(u16_type_erased.width, 2);
494
2
        assert_eq!(u16_type_erased.value, 64444);
495
2
        let u16_conv_back =
496
2
            UnsignedByteFieldU16::try_from(u16_type_erased).expect("conversion failed for u16");
497
2
        assert_eq!(u16, u16_conv_back);
498
2
        assert_eq!(u16_conv_back.value, 64444);
499
2
    }
500

            
501
    #[test]
502
2
    fn conversion_u16_fails() {
503
2
        let field = UnsignedByteField::new(4, 75000);
504
2
        let conv_fails = UnsignedByteFieldU16::try_from(field);
505
2
        assert!(conv_fails.is_err());
506
2
        let err = conv_fails.unwrap_err();
507
2
        match err {
508
            UnsignedByteFieldError::InvalidWidth {
509
2
                found,
510
2
                expected: Some(expected),
511
2
            } => {
512
2
                assert_eq!(found, 4);
513
2
                assert_eq!(expected, 2);
514
            }
515
            _ => {
516
                panic!("{}", format!("invalid error {err}"))
517
            }
518
        }
519
2
    }
520

            
521
    #[test]
522
2
    fn conversions_u32() {
523
2
        let u32 = UnsignedByteFieldU32::new(75000);
524
2
        let u32_type_erased = UnsignedByteField::from(u32);
525
2
        assert_eq!(u32_type_erased.width, 4);
526
2
        assert_eq!(u32_type_erased.value, 75000);
527
2
        let u32_conv_back =
528
2
            UnsignedByteFieldU32::try_from(u32_type_erased).expect("conversion failed for u32");
529
2
        assert_eq!(u32, u32_conv_back);
530
2
        assert_eq!(u32_conv_back.value, 75000);
531
2
    }
532

            
533
    #[test]
534
2
    fn conversion_u32_fails() {
535
2
        let field = UnsignedByteField::new(8, 75000);
536
2
        let conv_fails = UnsignedByteFieldU32::try_from(field);
537
2
        assert!(conv_fails.is_err());
538
2
        let err = conv_fails.unwrap_err();
539
2
        match err {
540
            UnsignedByteFieldError::InvalidWidth {
541
2
                found,
542
2
                expected: Some(expected),
543
2
            } => {
544
2
                assert_eq!(found, 8);
545
2
                assert_eq!(expected, 4);
546
            }
547
            _ => {
548
                panic!("{}", format!("invalid error {err}"))
549
            }
550
        }
551
2
    }
552

            
553
    #[test]
554
2
    fn conversions_u64() {
555
2
        let u64 = UnsignedByteFieldU64::new(5999999);
556
2
        let u64_type_erased = UnsignedByteField::from(u64);
557
2
        assert_eq!(u64_type_erased.width, 8);
558
2
        assert_eq!(u64_type_erased.value, 5999999);
559
2
        let u64_conv_back =
560
2
            UnsignedByteFieldU64::try_from(u64_type_erased).expect("conversion failed for u64");
561
2
        assert_eq!(u64, u64_conv_back);
562
2
        assert_eq!(u64_conv_back.value, 5999999);
563
2
    }
564

            
565
    #[test]
566
2
    fn conversion_u64_fails() {
567
2
        let field = UnsignedByteField::new(4, 60000);
568
2
        let conv_fails = UnsignedByteFieldU64::try_from(field);
569
2
        assert!(conv_fails.is_err());
570
2
        let err = conv_fails.unwrap_err();
571
2
        match err {
572
            UnsignedByteFieldError::InvalidWidth {
573
2
                found,
574
2
                expected: Some(expected),
575
2
            } => {
576
2
                assert_eq!(found, 4);
577
2
                assert_eq!(expected, 8);
578
            }
579
            _ => {
580
                panic!("{}", format!("invalid error {err}"))
581
            }
582
        }
583
2
    }
584

            
585
    #[test]
586
2
    fn type_erased_u8_write() {
587
2
        let u8 = UnsignedByteField::new(1, 5);
588
2
        assert_eq!(u8.size(), 1);
589
2
        let mut buf: [u8; 8] = [0; 8];
590
2
        u8.write_to_be_bytes(&mut buf)
591
2
            .expect("writing to raw buffer failed");
592
2
        assert_eq!(buf[0], 5);
593
15
        (1..8).for_each(|i| {
594
14
            assert_eq!(buf[i], 0);
595
15
        });
596
2
    }
597

            
598
    #[test]
599
2
    fn type_erased_u16_write() {
600
2
        let u16 = UnsignedByteField::new(2, 3823);
601
2
        assert_eq!(u16.size(), 2);
602
2
        let mut buf: [u8; 8] = [0; 8];
603
2
        u16.write_to_be_bytes(&mut buf)
604
2
            .expect("writing to raw buffer failed");
605
2
        let raw_val = u16::from_be_bytes(buf[0..2].try_into().unwrap());
606
2
        assert_eq!(raw_val, 3823);
607
12
        for val in buf.iter().skip(2) {
608
12
            assert_eq!(*val, 0);
609
        }
610
2
    }
611

            
612
    #[test]
613
2
    fn type_erased_u32_write() {
614
2
        let u32 = UnsignedByteField::new(4, 80932);
615
2
        assert_eq!(u32.size(), 4);
616
2
        let mut buf: [u8; 8] = [0; 8];
617
2
        u32.write_to_be_bytes(&mut buf)
618
2
            .expect("writing to raw buffer failed");
619
2
        let raw_val = u32::from_be_bytes(buf[0..4].try_into().unwrap());
620
2
        assert_eq!(raw_val, 80932);
621
9
        (4..8).for_each(|i| {
622
8
            assert_eq!(buf[i], 0);
623
9
        });
624
2
    }
625

            
626
    #[test]
627
2
    fn type_erased_u64_write() {
628
2
        let u64 = UnsignedByteField::new(8, 5999999);
629
2
        assert_eq!(u64.size(), 8);
630
2
        let mut buf: [u8; 8] = [0; 8];
631
2
        u64.write_to_be_bytes(&mut buf)
632
2
            .expect("writing to raw buffer failed");
633
2
        let raw_val = u64::from_be_bytes(buf[0..8].try_into().unwrap());
634
2
        assert_eq!(raw_val, 5999999);
635
2
    }
636

            
637
    #[test]
638
2
    fn type_erased_u8_construction() {
639
2
        let buf: [u8; 2] = [5, 10];
640
2
        let u8 = UnsignedByteField::new_from_be_bytes(1, &buf).expect("construction failed");
641
2
        assert_eq!(u8.width, 1);
642
2
        assert_eq!(u8.value, 5);
643
2
    }
644

            
645
    #[test]
646
2
    fn type_erased_u16_construction() {
647
2
        let buf: [u8; 2] = [0x10, 0x15];
648
2
        let u16 = UnsignedByteField::new_from_be_bytes(2, &buf).expect("construction failed");
649
2
        assert_eq!(u16.width, 2);
650
2
        assert_eq!(u16.value, 0x1015);
651
2
    }
652

            
653
    #[test]
654
2
    fn type_erased_u32_construction() {
655
2
        let buf: [u8; 4] = [0x01, 0x02, 0x03, 0x04];
656
2
        let u32 = UnsignedByteField::new_from_be_bytes(4, &buf).expect("construction failed");
657
2
        assert_eq!(u32.width, 4);
658
2
        assert_eq!(u32.value, 0x01020304);
659
2
    }
660

            
661
    #[test]
662
2
    fn type_erased_u64_construction() {
663
2
        let buf: [u8; 8] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
664
2
        let u64 = UnsignedByteField::new_from_be_bytes(8, &buf).expect("construction failed");
665
2
        assert_eq!(u64.width, 8);
666
2
        assert_eq!(u64.value, 0x0102030405060708);
667
2
    }
668

            
669
    #[test]
670
2
    fn type_u16_target_buf_too_small() {
671
2
        let u16 = UnsignedByteFieldU16::new(500);
672
2
        let mut buf: [u8; 1] = [0; 1];
673
2
        let res = u16.write_to_be_bytes(&mut buf);
674
2
        assert!(res.is_err());
675
2
        let err = res.unwrap_err();
676
2
        match err {
677
2
            ByteConversionError::ToSliceTooSmall { found, expected } => {
678
2
                assert_eq!(found, 1);
679
2
                assert_eq!(expected, 2);
680
            }
681
            _ => {
682
                panic!("invalid exception")
683
            }
684
        }
685
2
    }
686

            
687
    #[test]
688
2
    fn type_erased_u16_target_buf_too_small() {
689
2
        let u16 = UnsignedByteField::new(2, 500);
690
2
        let mut buf: [u8; 1] = [0; 1];
691
2
        let res = u16.write_to_be_bytes(&mut buf);
692
2
        assert!(res.is_err());
693
2
        let err = res.unwrap_err();
694
2
        match err {
695
2
            ByteConversionError::ToSliceTooSmall { found, expected } => {
696
2
                assert_eq!(found, 1);
697
2
                assert_eq!(expected, 2);
698
            }
699
            _ => {
700
                panic!("invalid exception {}", err)
701
            }
702
        }
703
2
        let u16 = UnsignedByteField::new_from_be_bytes(2, &buf);
704
2
        assert!(u16.is_err());
705
2
        let err = u16.unwrap_err();
706
        if let UnsignedByteFieldError::ByteConversionError(
707
2
            ByteConversionError::FromSliceTooSmall { found, expected },
708
2
        ) = err
709
        {
710
2
            assert_eq!(expected, 2);
711
2
            assert_eq!(found, 1);
712
        } else {
713
            panic!("unexpected exception {}", err);
714
        }
715
2
    }
716

            
717
    #[test]
718
2
    fn type_u32_target_buf_too_small() {
719
2
        let u16 = UnsignedByteFieldU32::new(500);
720
2
        let mut buf: [u8; 3] = [0; 3];
721
2
        let res = u16.write_to_be_bytes(&mut buf);
722
2
        assert!(res.is_err());
723
2
        let err = res.unwrap_err();
724
2
        match err {
725
2
            ByteConversionError::ToSliceTooSmall { found, expected } => {
726
2
                assert_eq!(found, 3);
727
2
                assert_eq!(expected, 4);
728
            }
729
            _ => {
730
                panic!("invalid exception")
731
            }
732
        }
733
2
    }
734
}