serial_line_ip/
decoder.rs

1use super::*;
2
3/// SLIP decode context
4pub struct Decoder {
5    header_found: bool,
6    esc_seq: [u8; 4],
7    esc_seq_len: usize,
8}
9
10impl Decoder {
11    /// Create a new context for SLIP decoding
12    pub fn new() -> Self {
13        Decoder {
14            header_found: false,
15            esc_seq: [0; 4],
16            esc_seq_len: 0,
17        }
18    }
19
20    /// SLIP decode the input slice into the output slice.
21    ///
22    /// This returns the number of bytes processed, an output slice and an indication of
23    /// the end of the packet.
24    pub fn decode<'a>(&mut self, input: &'a [u8], output: &'a mut [u8])
25        -> Result<(usize, &'a [u8], bool)>
26    {
27        let input_len = input.len();
28        let mut stream = input;
29        if !self.header_found {
30            stream = self.decode_header(stream)?;
31        }
32        let res = self.decode_stream(stream, output)?;
33
34        Ok((input_len - res.0.len(), res.1, res.2))
35    }
36
37    /// Either process the header successfully or return an error
38    fn decode_header<'a>(&mut self, input: &'a [u8]) -> Result<&'a [u8]> {
39        if input.len() < 1 {
40            // TODO: decode partial headers! For now, just error out...
41            return Err(Error::BadHeaderDecode);
42        }
43
44        if input[0] != END {
45            return Err(Error::BadHeaderDecode);
46        }
47        self.header_found = true;
48
49        Ok(&input[1..])
50    }
51
52    /// Core stream processing
53    fn decode_stream<'a>(&mut self, input: &'a [u8], output: &'a mut [u8])
54        -> Result<(&'a [u8], &'a [u8], bool)>
55    {
56        let mut in_byte = 0;
57        let mut out_byte = 0;
58        let mut end = false;
59
60        loop {
61            if in_byte == input.len() || out_byte == output.len() {
62                break;
63            }
64
65            if self.esc_seq_len > 0 {
66                match input[in_byte] {
67                    ESC_END => {
68                        output[out_byte] = END
69                    }
70                    ESC_ESC => {
71                        output[out_byte] = ESC
72                    }
73                    _ => return Err(Error::BadEscapeSequenceDecode),
74                }
75                out_byte += 1;
76                self.esc_sequence_empty();
77            } else {
78                match input[in_byte] {
79                    ESC => {
80                        self.esc_sequence_push(ESC);
81                    }
82                    END => {
83                        in_byte += 1;
84                        end = true;
85                        break;
86                    }
87                    _ => {
88                        output[out_byte] = input[in_byte];
89                        out_byte += 1;
90                    }
91                }
92            }
93            in_byte += 1;
94        }
95
96        Ok((&input[in_byte..], &output[..out_byte], end))
97    }
98
99    /// Push a byte onto the escape sequence
100    fn esc_sequence_push(&mut self, byte: u8) {
101        self.esc_seq[self.esc_seq_len] = byte;
102        self.esc_seq_len += 1;
103    }
104
105    /// Reset the escape sequence
106    fn esc_sequence_empty(&mut self) {
107        self.esc_seq_len = 0;
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn empty_decode() {
117        const INPUT: [u8; 2] = [0xc0, 0xc0];
118        let mut output: [u8; 32] = [0; 32];
119
120        let mut slip = Decoder::new();
121        let res = slip.decode(&INPUT, &mut output).unwrap();
122        assert_eq!(INPUT.len(), res.0);
123        assert_eq!(&[0;0], res.1);
124        assert_eq!(true, res.2);
125    }
126
127    #[test]
128    fn simple_decode() {
129        const INPUT: [u8; 7] = [0xc0, 0x01, 0x02, 0x03, 0x04, 0x05, 0xc0];
130        const DATA: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x05];
131        let mut output: [u8; 32] = [0; 32];
132
133        let mut slip = Decoder::new();
134        let res = slip.decode(&INPUT, &mut output).unwrap();
135        assert_eq!(INPUT.len(), res.0);
136        assert_eq!(&DATA, res.1);
137        assert_eq!(true, res.2);
138    }
139
140    /// Ensure that [ESC, ESC_END] -> [END]
141    #[test]
142    fn decode_esc_then_esc_end_sequence() {
143        const INPUT: [u8; 6] = [0xc0, 0x01, 0xdb, 0xdc, 0x03, 0xc0];
144        const DATA: [u8; 3] = [0x01, 0xc0, 0x03];
145        let mut output: [u8; 200] = [0; 200];
146
147        let mut slip = Decoder::new();
148        let res = slip.decode(&INPUT, &mut output).unwrap();
149        assert_eq!(INPUT.len(), res.0);
150        assert_eq!(&DATA, res.1);
151        assert_eq!(true, res.2);
152    }
153
154    /// Ensure that [ESC, ESC_ESC] -> [ESC]
155    #[test]
156    fn decode_esc_then_esc_esc_sequence() {
157        const INPUT: [u8; 6] = [0xc0, 0x01, 0xdb, 0xdd, 0x03, 0xc0];
158        const DATA: [u8; 3] = [0x01, 0xdb, 0x03];
159        let mut output: [u8; 200] = [0; 200];
160
161        let mut slip = Decoder::new();
162        let res = slip.decode(&INPUT, &mut output).unwrap();
163        assert_eq!(INPUT.len(), res.0);
164        assert_eq!(&DATA, res.1);
165        assert_eq!(true, res.2);
166    }
167
168    #[test]
169    fn multi_part_decode() {
170        const INPUT_1: [u8; 6] = [0xc0, 0x01, 0x02, 0x03, 0x04, 0x05];
171        const INPUT_2: [u8; 6] = [0x05, 0x06, 0x07, 0x08, 0x09, 0xc0];
172        const DATA_1: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x05];
173        const DATA_2: [u8; 5] = [0x05, 0x06, 0x07, 0x08, 0x09];
174        let mut output: [u8; 200] = [0; 200];
175
176        let mut slip = Decoder::new();
177        let mut offset = 0;
178        {
179            let res = slip.decode(&INPUT_1, &mut output[offset..]).unwrap();
180            assert_eq!(INPUT_1.len(), res.0);
181            assert_eq!(&DATA_1, res.1);
182            assert_eq!(false, res.2);
183            offset += res.1.len();
184        }
185        {
186            let res = slip.decode(&INPUT_2, &mut output[offset..]).unwrap();
187            assert_eq!(INPUT_2.len(), res.0);
188            assert_eq!(&DATA_2, res.1);
189            assert_eq!(true, res.2);
190            offset += res.1.len();
191        }
192        assert_eq!(10, offset);
193    }
194}