slip_codec/
decoder.rs

1use crate::{END, ESC, ESC_END, ESC_ESC};
2use std::io::{Read, Write};
3
4/// SLIP decoder error type
5#[derive(Debug)]
6pub enum SlipError {
7    FramingError,
8    OversizedPacket,
9    EndOfStream,
10    ReadError(std::io::Error),
11}
12
13impl From<SlipError> for std::io::Error {
14    fn from(err: SlipError) -> std::io::Error {
15        match err {
16            SlipError::FramingError => {
17                std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", err))
18            }
19            SlipError::OversizedPacket => {
20                std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", err))
21            }
22            SlipError::EndOfStream => {
23                std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", err))
24            }
25            SlipError::ReadError(err) => err,
26        }
27    }
28}
29
30impl From<std::io::Error> for SlipError {
31    fn from(err: std::io::Error) -> Self {
32        SlipError::ReadError(err)
33    }
34}
35
36pub type SlipResult = std::result::Result<usize, self::SlipError>;
37
38#[derive(Debug)]
39enum State {
40    Normal,
41    Error,
42    Escape,
43}
44
45/// SLIP decoder context
46#[derive(Debug)]
47pub struct SlipDecoder {
48    count: usize,
49    state: State,
50}
51
52impl SlipDecoder {
53    /// Creates a new context with the given maximum buffer size.
54    pub fn new() -> Self {
55        Self {
56            count: 0usize,
57            state: State::Normal,
58        }
59    }
60
61    fn push(&mut self, sink: &mut dyn Write, value: u8) -> self::SlipResult {
62        match sink.write(&[value]) {
63            Ok(len) => {
64                if len != 1 {
65                    Err(SlipError::OversizedPacket)
66                } else {
67                    self.count += 1;
68                    Ok(1usize)
69                }
70            }
71            Err(error) => Err(error.into()),
72        }
73    }
74
75    /// Attempts to decode a single SLIP frame from the given source.
76    ///
77    /// # Arguments
78    ///
79    /// * `source` - Encoded SLIP data source implementing the std::io::Read
80    ///              trait
81    ///
82    /// Returns a Vec<u8> containing a decoded message or an empty Vec<u8> if
83    /// of the source data was reached.
84    ///
85    pub fn decode(&mut self, source: &mut dyn Read, sink: &mut dyn Write) -> self::SlipResult {
86        for value in source.bytes() {
87            let value = value?;
88
89            match self.state {
90                State::Normal => match value {
91                    END => {
92                        if self.count > 0 {
93                            let len = self.count;
94
95                            self.count = 0usize;
96
97                            return Ok(len);
98                        }
99                    }
100                    ESC => {
101                        self.state = State::Escape;
102                    }
103                    _ => {
104                        self.push(sink, value)?;
105                    }
106                },
107                State::Error => {
108                    if value == END {
109                        self.count = 0usize;
110                        self.state = State::Normal;
111                    }
112                }
113                State::Escape => match value {
114                    ESC_END => {
115                        self.push(sink, END)?;
116                        self.state = State::Normal;
117                    }
118                    ESC_ESC => {
119                        self.push(sink, ESC)?;
120                        self.state = State::Normal;
121                    }
122                    _ => {
123                        self.state = State::Error;
124
125                        return Err(SlipError::FramingError);
126                    }
127                },
128            }
129        }
130
131        Err(SlipError::EndOfStream)
132    }
133}
134
135impl Default for SlipDecoder {
136    fn default() -> Self {
137        Self::new()
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn empty_decode() {
147        const INPUT: [u8; 2] = [0xc0, 0xc0];
148
149        let mut slip = SlipDecoder::new();
150        let mut buf: Vec<u8> = Vec::new();
151        let res = slip.decode(&mut INPUT.as_ref(), &mut buf);
152        assert!(res.is_err());
153        assert!(buf.is_empty());
154    }
155
156    #[test]
157    fn simple_decode() {
158        const INPUT: [u8; 7] = [0xc0, 0x01, 0x02, 0x03, 0x04, 0x05, 0xc0];
159        const DATA: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x05];
160
161        let mut slip = SlipDecoder::new();
162        let mut buf = [0u8; DATA.len()];
163        let len = slip.decode(&mut INPUT.as_ref(), &mut buf.as_mut()).unwrap();
164        assert_eq!(DATA.len(), len);
165        assert_eq!(DATA.len(), buf.len());
166        assert_eq!(&DATA, &buf);
167    }
168
169    /// Ensure that [ESC, ESC_END] -> [END]
170    #[test]
171    fn decode_esc_then_esc_end_sequence() {
172        const INPUT: [u8; 6] = [0xc0, 0x01, 0xdb, 0xdc, 0x03, 0xc0];
173        const DATA: [u8; 3] = [0x01, 0xc0, 0x03];
174
175        let mut slip = SlipDecoder::new();
176        let mut buf: Vec<u8> = Vec::new();
177        let len = slip.decode(&mut INPUT.as_ref(), &mut buf).unwrap();
178        assert_eq!(DATA.len(), len);
179        assert_eq!(DATA.len(), buf.len());
180        assert_eq!(&DATA, buf.as_slice());
181    }
182
183    /// Ensure that [ESC, ESC_ESC] -> [ESC]
184    #[test]
185    fn decode_esc_then_esc_esc_sequence() {
186        const INPUT: [u8; 6] = [0xc0, 0x01, 0xdb, 0xdd, 0x03, 0xc0];
187        const DATA: [u8; 3] = [0x01, 0xdb, 0x03];
188
189        let mut slip = SlipDecoder::new();
190        let mut buf: Vec<u8> = Vec::new();
191        let len = slip.decode(&mut INPUT.as_ref(), &mut buf).unwrap();
192        assert_eq!(DATA.len(), len);
193        assert_eq!(DATA.len(), buf.len());
194        assert_eq!(&DATA, buf.as_slice());
195    }
196
197    #[test]
198    fn multi_part_decode() {
199        const INPUT_1: [u8; 6] = [0xc0, 0x01, 0x02, 0x03, 0x04, 0x05];
200        const INPUT_2: [u8; 6] = [0x05, 0x06, 0x07, 0x08, 0x09, 0xc0];
201        const DATA: [u8; 10] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09];
202
203        let mut slip = SlipDecoder::new();
204        let mut buf: Vec<u8> = Vec::new();
205
206        {
207            let res = slip.decode(&mut INPUT_1.as_ref(), &mut buf);
208            assert!(res.is_err());
209            assert_eq!(5, buf.len());
210        }
211
212        {
213            let len = slip.decode(&mut INPUT_2.as_ref(), &mut buf).unwrap();
214            assert_eq!(DATA.len(), len);
215            assert_eq!(DATA.len(), buf.len());
216            assert_eq!(&DATA, buf.as_slice());
217        }
218    }
219
220    #[test]
221    fn compound_decode() {
222        const INPUT: [u8; 13] = [
223            0xc0, 0x01, 0x02, 0x03, 0x04, 0x05, 0xc0, 0x05, 0x06, 0x07, 0x08, 0x09, 0xc0,
224        ];
225        const DATA_1: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x05];
226        const DATA_2: [u8; 5] = [0x05, 0x06, 0x07, 0x08, 0x09];
227
228        let mut slip = SlipDecoder::new();
229        let reader: &mut dyn std::io::Read = &mut INPUT.as_ref();
230
231        {
232            let mut buf: Vec<u8> = Vec::new();
233            let len = slip.decode(reader, &mut buf).unwrap();
234            assert_eq!(DATA_1.len(), len);
235            assert_eq!(DATA_1.len(), buf.len());
236            assert_eq!(&DATA_1, buf.as_slice());
237        }
238
239        {
240            let mut buf: Vec<u8> = Vec::new();
241            let len = slip.decode(reader, &mut buf).unwrap();
242            assert_eq!(DATA_2.len(), len);
243            assert_eq!(DATA_2.len(), buf.len());
244            assert_eq!(&DATA_2, buf.as_slice());
245        }
246    }
247}