Skip to main content

fennec_modbus/protocol/codec/
bit_size.rs

1pub trait BitSize {
2    /// Number of bits occupied by the value.
3    const N_BITS: u16;
4
5    /// Number of whole bytes occupied by the value.
6    #[expect(clippy::cast_possible_truncation)]
7    const N_BYTES: u8 = {
8        let n_bytes = Self::N_BITS.div_ceil(8);
9        assert!(n_bytes <= u8::MAX as u16, "value type exceeds 255 bytes");
10        n_bytes as u8
11    };
12
13    /// Number of whole words occupied by the value.
14    const N_WORDS: u16 = Self::N_BITS.div_ceil(16);
15
16    /// Assert that the number of bytes in the payload is valid.
17    ///
18    /// If the value type is too big, the assertion would fire at compile time.
19    fn assert_valid<const N_MAX_BYTES: u8>() {
20        const {
21            assert!(Self::N_BYTES >= 1, "value type must be non-empty");
22            assert!(Self::N_BYTES <= N_MAX_BYTES, "value is too large");
23        };
24    }
25}
26
27impl<T: BitSize, const N: usize> BitSize for &[T; N] {
28    #[expect(clippy::cast_possible_truncation)]
29    const N_BITS: u16 = match (T::N_BITS as usize).checked_mul(N) {
30        Some(n_bits) if n_bits <= u16::MAX as usize => n_bits as u16,
31        _ => panic!("array size overflow"),
32    };
33}
34
35impl<T: BitSize, const N: usize> BitSize for [T; N] {
36    const N_BITS: u16 = <&[T; N]>::N_BITS;
37}
38
39macro_rules! impl_for {
40    ($type:ty, $n_bits:literal) => {
41        impl BitSize for $type {
42            const N_BITS: u16 = $n_bits;
43        }
44    };
45}
46
47impl_for!(u8, 8);
48impl_for!(i8, 8);
49impl_for!(u16, 16);
50impl_for!(i16, 16);
51impl_for!(u32, 32);
52impl_for!(i32, 32);
53impl_for!(u64, 64);
54impl_for!(i64, 64);
55impl_for!(u128, 128);
56impl_for!(i128, 128);