acn_protocol/
root_layer.rs

1use crate::AcnError;
2use core::error::Error;
3
4pub trait RootLayerCodec {
5    type Error: Error + From<AcnError>;
6
7    fn size(&self) -> usize {
8        self.preamble_length() + self.pdu_block_length() + self.postamble_length()
9    }
10
11    fn preamble_length(&self) -> usize {
12        0
13    }
14
15    fn encode_preamble(&self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
16        Ok(self.preamble_length())
17    }
18
19    fn pdu_block_length(&self) -> usize {
20        0
21    }
22
23    fn encode_pdu_block(&self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
24        Ok(self.pdu_block_length())
25    }
26
27    fn postamble_length(&self) -> usize {
28        0
29    }
30
31    fn encode_postamble(&self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
32        Ok(self.postamble_length())
33    }
34
35    fn encode(&self, buf: &mut [u8]) -> Result<usize, Self::Error> {
36        if buf.len() < self.size() {
37            return Err(AcnError::InvalidBufferLength(buf.len()).into());
38        }
39
40        let mut offset = 0;
41
42        offset += self.encode_preamble(&mut buf[offset..])?;
43
44        offset += self.encode_pdu_block(&mut buf[offset..])?;
45
46        offset += self.encode_postamble(&mut buf[offset..])?;
47
48        Ok(offset)
49    }
50
51    fn decode(buf: &[u8]) -> Result<Self, Self::Error>
52    where
53        Self: Sized;
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    struct TestPdu {
61        target_id: u8,
62        source_id: u8,
63        data: u32,
64    }
65
66    struct TestRootLayerPacket {
67        pdu1: TestPdu,
68        pdu2: TestPdu,
69    }
70
71    impl RootLayerCodec for TestRootLayerPacket {
72        type Error = AcnError;
73
74        fn preamble_length(&self) -> usize {
75            4
76        }
77
78        fn encode_preamble(&self, buf: &mut [u8]) -> Result<usize, AcnError> {
79            buf[0..4].copy_from_slice(&[0x01, 0x02, 0x03, 0x04]);
80
81            Ok(self.preamble_length())
82        }
83
84        fn pdu_block_length(&self) -> usize {
85            12
86        }
87
88        fn encode_pdu_block(&self, buf: &mut [u8]) -> Result<usize, AcnError> {
89            buf[0] = self.pdu1.target_id;
90            buf[1] = self.pdu1.source_id;
91            buf[2..6].copy_from_slice(&self.pdu1.data.to_be_bytes());
92            buf[6] = self.pdu2.target_id;
93            buf[7] = self.pdu2.source_id;
94            buf[8..12].copy_from_slice(&self.pdu2.data.to_be_bytes());
95
96            Ok(self.pdu_block_length())
97        }
98
99        fn postamble_length(&self) -> usize {
100            4
101        }
102
103        fn encode_postamble(&self, buf: &mut [u8]) -> Result<usize, AcnError> {
104            buf[0..4].copy_from_slice(&[0x05, 0x06, 0x07, 0x08]);
105
106            Ok(self.postamble_length())
107        }
108
109        fn decode(buf: &[u8]) -> Result<Self, Self::Error> {
110            if buf.len() < 4 {
111                return Err(AcnError::InvalidBufferLength(buf.len()));
112            }
113
114            if buf[0..4] != [0x01, 0x02, 0x03, 0x04] {
115                return Err(AcnError::InvalidPreamble);
116            }
117
118            let pdu1 = TestPdu {
119                target_id: buf[0],
120                source_id: buf[1],
121                data: u32::from_be_bytes(buf[2..6].try_into()?),
122            };
123
124            let pdu2 = TestPdu {
125                target_id: buf[6],
126                source_id: buf[7],
127                data: u32::from_be_bytes(buf[8..12].try_into()?),
128            };
129
130            if buf[12..16] != [0x05, 0x06, 0x07, 0x08] {
131                return Err(AcnError::InvalidPostamble);
132            }
133
134            Ok(Self { pdu1, pdu2 })
135        }
136    }
137
138    #[test]
139    fn should_encode_root_layer_packet() {
140        let buf = &mut [0u8; 20];
141
142        let root_layer_packet = TestRootLayerPacket {
143            pdu1: TestPdu {
144                target_id: 0x01,
145                source_id: 0x02,
146                data: 0x12345678,
147            },
148            pdu2: TestPdu {
149                target_id: 0x03,
150                source_id: 0x04,
151                data: 0x87654321,
152            },
153        };
154
155        let bytes_written = root_layer_packet.encode(buf).unwrap();
156
157        assert_eq!(bytes_written, 20);
158
159        assert_eq!(
160            buf,
161            &[
162                0x01, // Preamble Byte 1
163                0x02, // Preamble Byte 2
164                0x03, // Preamble Byte 3
165                0x04, // Preamble Byte 4
166                0x01, // PDU1 Target ID
167                0x02, // PDU1 Source ID
168                0x12, // PDU1 Data Byte 1
169                0x34, // PDU1 Data Byte 2
170                0x56, // PDU1 Data Byte 3
171                0x78, // PDU1 Data Byte 4
172                0x03, // PDU2 Target ID
173                0x04, // PDU2 Source ID
174                0x87, // PDU2 Data Byte 1
175                0x65, // PDU2 Data Byte 2
176                0x43, // PDU2 Data Byte 3
177                0x21, // PDU2 Data Byte 4
178                0x05, // Postamble Byte 1
179                0x06, // Postamble Byte 2
180                0x07, // Postamble Byte 3
181                0x08, // Postamble Byte 4
182            ]
183        );
184    }
185}