rusty_slip/
slip.rs

1#[non_exhaustive]
2struct SlipCode;
3
4/// SLIP codes as defined in [RFC1055](https://datatracker.ietf.org/doc/html/rfc1055)
5impl SlipCode {
6    pub const END: u8 = 192;
7    pub const ESC: u8 = 219;
8    pub const ESC_END: u8 = 220;
9    pub const ESC_ESC: u8 = 221;
10}
11
12
13/// SLIP-encodes a byte-slice into the given buffer as described in
14/// [RFC1055](https://datatracker.ietf.org/doc/html/rfc1055). Returns size of encoded data in bytes.
15pub fn encode(encoded_data_buf: &mut[u8], data: &[u8]) -> usize {
16    let mut idx = 0;
17
18    for b in data {
19        match *b {
20            SlipCode::END => {
21                // END -> ESC ESC_END
22                encoded_data_buf[idx] = SlipCode::ESC;
23                encoded_data_buf[idx + 1] = SlipCode::ESC_END;
24                idx += 2;
25            }
26            SlipCode::ESC => {
27                // ESC -> ESC ESC_ESC
28                encoded_data_buf[idx] = SlipCode::ESC;
29                encoded_data_buf[idx + 1] = SlipCode::ESC_ESC;
30                idx += 2;
31            }
32            _ => {
33                // no ESC needed, copy to buffer
34                encoded_data_buf[idx] = *b;
35                idx += 1;
36            }
37        }
38    }
39
40    // signal END of SLIP packet
41    encoded_data_buf[idx] = SlipCode::END;
42    idx+1
43}
44
45
46/// A SLIP decoder which supports split up packets. This occurs when for example the first half of a
47/// SLIP packet is transmitted at the end of a UART DMA read and the other half in the next
48/// UART DMA read. Also works over multiple calls of [`Self::decode`]. Decoded
49/// packets are available via [`Self::are_decoded_packets_available`] and [`Self::get_packets`].
50/// # Example
51///
52/// ```
53/// use rusty_slip::slip::{encode, SlipDecoder};
54/// use std::str;
55///
56/// // encode a slice
57/// let data = "hello world!";
58/// // make sure tx_buf is large enough
59/// let mut tx_buf: [u8; 256] = [0; 256];
60/// encode(&mut tx_buf, data.as_bytes());///
61///
62/// // decode packet
63/// let mut decoder = SlipDecoder::new();
64/// decoder.decode(&tx_buf);
65/// let packets = decoder.get_packets();
66/// let first_packet = packets.first().unwrap();
67///
68/// // decode Vec<u8> into a string
69/// let packet_message = str::from_utf8(first_packet).expect("Could not convert decoded SLIP packet into a string!");
70/// println!("{}", packet_message);
71///
72/// assert_eq!(data, packet_message);
73/// ```
74pub struct SlipDecoder {
75    decoded_packets: Vec<Vec<u8>>,
76    decode_buf: Vec<u8>,
77    last_byte_was_esc: bool
78}
79
80
81impl SlipDecoder {
82    /// Instantiates a SlipDecoder.
83    pub fn new() -> SlipDecoder {
84        SlipDecoder {
85            decoded_packets: Vec::new(),
86            decode_buf: Vec::new(),
87            last_byte_was_esc: false
88        }
89    }
90
91    /// This method indicates whether new decoded SLIP packets are available.
92    pub fn are_decoded_packets_available(&self) -> bool {
93        !self.decoded_packets.is_empty()
94    }
95
96    fn build_packet(&mut self) {
97        let msg = self.decode_buf.clone();
98
99        self.decoded_packets.push(msg);
100        self.decode_buf.clear();
101    }
102
103    /// This method returns all decoded packets and removes them from the decoders memory.
104    pub fn get_packets(&mut self) -> Vec<Vec<u8>> {
105        let res = self.decoded_packets.clone();
106        self.decoded_packets.clear();
107        res
108    }
109
110    /// This method tries to decode the given SLIP data into one or more packets. Packets which
111    /// are not terminated at the end of the given slice are stored in the internal buffer
112    /// of the decoder. The decoder continues decoding these packets on the next call(s) of this method
113    /// with the new data supplied. Decoded packets are signaled via [`Self::are_decoded_packets_available`] and
114    /// can be fetched via [`Self::get_packets`]
115    pub fn decode(&mut self, encoded_data: &[u8]) {
116        for b in encoded_data {
117            if self.last_byte_was_esc {
118                match *b {
119                    SlipCode::ESC_END => {
120                        self.decode_buf.push(SlipCode::END);
121                    }
122                    SlipCode::ESC_ESC => {
123                        self.decode_buf.push(SlipCode::ESC);
124                    }
125                    _ => {
126                        self.decode_buf.push(*b);
127                    }
128                }
129                // reset ESC flag
130                self.last_byte_was_esc = false;
131            } else {
132                match *b {
133                    SlipCode::ESC => {
134                        self.last_byte_was_esc = true;
135                    },
136                    SlipCode::END => {
137                        // end of this SLIP packet
138                        self.build_packet();
139                    }
140                    _ => {
141                        self.decode_buf.push(*b);
142                    }
143                }
144            }
145        }
146    }
147}
148
149
150
151#[cfg(test)]
152mod tests {
153    use crate::slip::{encode, SlipDecoder};
154    use rand::Rng;
155    use quickcheck::quickcheck;
156
157    quickcheck! {
158        fn sending_split_up_packet_over_2_bufs(data: Vec<u8>) -> bool {
159
160            // splitting a single element would not make sense
161            if data.len() < 2 {
162                return true;
163            }
164
165            // generate random buffer split
166            let random_split = rand::thread_rng().gen_range(0..data.len());
167
168
169            // SLIP encode given data
170            let mut tx_buf: [u8; 256] = [0; 256];
171            let num_of_bytes_to_send = encode(&mut tx_buf, data.as_slice());
172
173            let mut decoder = SlipDecoder::new();
174
175            // decode twice with both buffer parts
176            decoder.decode(&tx_buf[0..random_split]);
177            decoder.decode(&tx_buf[random_split..num_of_bytes_to_send]);
178
179            let packets = decoder.get_packets();
180            let msg = packets.first().unwrap();
181
182            *msg == data
183        }
184    }
185
186    quickcheck! {
187        fn encode_decode_should_yield_input_data(data: Vec<u8>) -> bool {
188
189            // SLIP encode given data
190            let mut tx_buf: [u8; 256] = [0; 256];
191            encode(&mut tx_buf, data.as_slice());
192
193            let mut decoder = SlipDecoder::new();
194            decoder.decode(&tx_buf);
195
196            let packets = decoder.get_packets();
197            let msg = packets.first().unwrap();
198
199            *msg == data
200        }
201    }
202
203
204}