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