encdec_base/helpers/
bitflags.rs

1use core::fmt::Debug;
2
3use bitflags::{Flag, Flags, Bits};
4
5use crate::{decode::DecodeOwned, encode::Encode, EncDec, Error};
6
7/// Marker trait for auto-implementing encode and decode for bitflags objects
8/// 
9/// Note: this only works where Flags::Bits is a primitive supported by encdec
10pub trait EncDecBitflags {}
11
12impl <T: Flags + Debug + EncDecBitflags> Encode for T where 
13    <T as Flags>::Bits: Encode<Error = Error>,
14{
15    type Error = crate::Error;
16
17    fn encode_len(&self) -> Result<usize, Self::Error> {
18        Ok(size_of::<<T as Flags>::Bits>())
19    }
20
21    fn encode(&self, buff: &mut [u8]) -> Result<usize, Self::Error> {
22        // Check buffer length
23        if buff.len() < self.encode_len()? {
24            return Err(Error::Length);
25        }
26
27        // Fetch bits repr
28        let b = self.bits();
29
30        // Encode using default encoder
31        b.encode(buff)
32    }
33}
34
35impl <T: Flags + Debug + EncDecBitflags> DecodeOwned for T where 
36    <T as Flags>::Bits: DecodeOwned<Output = <T as Flags>::Bits, Error = Error>,
37{
38    type Error = crate::Error;
39    
40    type Output = T;
41    
42    fn decode_owned(buff: &[u8]) -> Result<(Self::Output, usize), Self::Error> {
43        if buff.len() < size_of::<<T as Flags>::Bits>() {
44            return Err(Error::Length);
45        }
46
47        let (bits, n) = <T as Flags>::Bits::decode_owned(buff)?;
48
49        let f = <T as Flags>::from_bits_retain(bits);
50
51        Ok((f, n))
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use bitflags::bitflags;
58    
59    use crate::helpers::test_encode_decode;
60
61    use super::*;
62
63    bitflags!{
64        #[derive(Copy, Clone, Debug, PartialEq)]
65        pub struct TestFlags: u16 {
66            const A = 0b0001;
67            const B = 0b0010;
68        }
69    }
70
71    impl EncDecBitflags for TestFlags {}
72
73    #[test]
74    fn bitflags_encode_decode() {
75        let tests = &[
76            TestFlags::A,
77            TestFlags::B,
78            TestFlags::empty(),
79            TestFlags::all(),
80        ];
81
82
83        let mut buff = [0u8; 32];
84        for t in tests {
85            test_encode_decode(&mut buff, *t);
86        }
87    }
88
89    #[test]
90    fn bitflags_encode_fails() {
91        
92        let a = TestFlags::A;
93        let mut b = [0u8; 1];
94
95        // Check encode buffer length
96        a.encode(&mut b).expect_err("buffer too short");
97        // Check decode buffer length
98        TestFlags::decode_owned(&b).expect_err("buffer too short");
99    }
100}