acn_protocol/
root_layer.rs

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