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}