hdlc/lib.rs
1//! # hdlc
2//! Frames the data or parses a frame. Rust implementation of a High-level Data Link Control (HDLC)
3//! library with support of the IEEE standard.
4//!
5//! ## Usage
6//!
7//! ### Encode packet
8//! ```rust
9//! use hdlc::{SpecialChars, encode};
10//!
11//! let msg: Vec<u8> = vec![0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09];
12//! let cmp: Vec<u8> = vec![0x7E, 0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09, 0x7E];
13//!
14//! let result = encode(&msg, SpecialChars::default());
15//!
16//! assert!(result.is_ok());
17//! assert_eq!(result.unwrap(), cmp);
18//! ```
19//!
20//! ### Custom Special Characters
21//! ```rust
22//! use hdlc::{SpecialChars, encode};
23//!
24//! let msg: Vec<u8> = vec![0x01, 0x7E, 0x70, 0x50, 0x00, 0x05, 0x80, 0x09];
25//! let cmp: Vec<u8> = vec![0x71, 0x01, 0x7E, 0x70, 0x50, 0x50, 0x00, 0x05, 0x80, 0x09, 0x71];
26//! let chars = SpecialChars::new(0x71, 0x70, 0x51, 0x50);
27//!
28//! let result = encode(&msg, chars);
29//!
30//! assert!(result.is_ok());
31//! assert_eq!(result.unwrap(), cmp)
32//! ```
33//!
34//! ### Decode packet
35//! ```rust
36//! use hdlc::{SpecialChars, decode};
37//!
38//! let chars = SpecialChars::default();
39//! let msg: Vec<u8> = vec![
40//! chars.fend, 0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09, chars.fend,
41//! ];
42//! let cmp: Vec<u8> = vec![0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09];
43//!
44//! let result = decode(&msg, chars);
45//!
46//! assert!(result.is_ok());
47//! assert_eq!(result.unwrap(), cmp);
48//! ```
49//!
50//! ### Decode slice packet
51//! ```rust
52//! use hdlc::{SpecialChars, decode_slice};
53//!
54//! let chars = SpecialChars::default();
55//! let mut msg = [
56//! chars.fend, 0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09, chars.fend,
57//! ];
58//! let cmp = [0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09];
59//!
60//! let result = decode_slice(&mut msg, chars);
61//!
62//! assert!(result.is_ok());
63//! assert_eq!(result.unwrap(), cmp);
64//! ```
65
66#![deny(missing_docs)]
67
68use thiserror::Error;
69
70use std::collections::HashSet;
71use std::default::Default;
72use std::io::Read;
73
74/// Special Character structure for holding the encode and decode values.
75/// IEEE standard values are defined below in Default.
76///
77/// # Default
78///
79/// * **FEND** = 0x7E;
80/// * **FESC** = 0x7D;
81/// * **TFEND** = 0x5E;
82/// * **TFESC** = 0x5D;
83#[derive(Debug, Copy, Clone)]
84pub struct SpecialChars {
85 /// Frame END. Byte that marks the beginning and end of a packet
86 pub fend: u8,
87 /// Frame ESCape. Byte that marks the start of a swap byte
88 pub fesc: u8,
89 /// Trade Frame END. Byte that is substituted for the FEND byte
90 pub tfend: u8,
91 /// Trade Frame ESCape. Byte that is substituted for the FESC byte
92 pub tfesc: u8,
93}
94
95impl Default for SpecialChars {
96 /// Creates the default SpecialChars structure for encoding/decoding a packet
97 fn default() -> SpecialChars {
98 SpecialChars {
99 fend: 0x7E,
100 fesc: 0x7D,
101 tfend: 0x5E,
102 tfesc: 0x5D,
103 }
104 }
105}
106impl SpecialChars {
107 /// Creates a new SpecialChars structure for encoding/decoding a packet
108 pub fn new(fend: u8, fesc: u8, tfend: u8, tfesc: u8) -> SpecialChars {
109 SpecialChars {
110 fend,
111 fesc,
112 tfend,
113 tfesc,
114 }
115 }
116}
117
118/// Produces escaped (encoded) message surrounded with `FEND`
119///
120/// # Inputs
121/// * **`Vec<u8>`**: A vector of the bytes you want to encode
122/// * **SpecialChars**: The special characters you want to swap
123///
124/// # Output
125///
126/// * **`Result<Vec<u8>>`**: Encoded output message
127///
128/// # Error
129///
130/// * **HDLCError::DuplicateSpecialChar**: Checks special characters for duplicates, if any of
131/// the `SpecialChars` are duplicate, throw an error. Displays "Duplicate special character".
132///
133/// # Todo
134///
135/// Catch more errors, like an incomplete packet
136///
137/// # Example
138/// ```rust
139/// let chars = hdlc::SpecialChars::default();
140/// let input: Vec<u8> = vec![0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09];
141/// let op_vec = hdlc::encode(&input.to_vec(), chars);
142/// ```
143pub fn encode(data: &[u8], s_chars: SpecialChars) -> Result<Vec<u8>, HDLCError> {
144 // Safety check to make sure the special character values are all unique
145 let mut set = HashSet::new();
146 if !set.insert(s_chars.fend)
147 || !set.insert(s_chars.fesc)
148 || !set.insert(s_chars.tfend)
149 || !set.insert(s_chars.tfesc)
150 {
151 return Err(HDLCError::DuplicateSpecialChar);
152 }
153
154 // Prealocate for speed. *2 is the max size it can be if EVERY char is swapped
155 let mut output = Vec::with_capacity(data.len() * 2);
156 // Iterator over the input that allows peeking
157 let input_iter = data.iter();
158
159 //Push initial FEND
160 output.push(s_chars.fend);
161
162 // Loop over every byte of the message
163 for value in input_iter {
164 match *value {
165 // FEND and FESC
166 val if val == s_chars.fesc => {
167 output.push(s_chars.fesc);
168 output.push(s_chars.tfesc);
169 }
170 val if val == s_chars.fend => {
171 output.push(s_chars.fesc);
172 output.push(s_chars.tfend);
173 }
174 // Handle any other bytes
175 _ => output.push(*value),
176 }
177 }
178
179 // Push final FEND
180 output.push(s_chars.fend);
181
182 Ok(output)
183}
184
185/// Produces unescaped (decoded) message without `FEND` characters.
186///
187/// # Inputs
188/// * **`Vec<u8>`**: A vector of the bytes you want to decode
189/// * **SpecialChars**: The special characters you want to swap
190///
191/// # Output
192///
193/// * **`Result<Vec<u8>>`**: Decoded output message
194///
195/// # Error
196///
197/// * **HDLCError::DuplicateSpecialChar**: Checks special characters for duplicates, if any of
198/// the `SpecialChars` are duplicate, throw an error. Displays "Duplicate special character".
199/// * **HDLCError::FendCharInData**: Checks to make sure the full decoded message is the full
200/// length. Found the `SpecialChars::fend` inside the message.
201/// * **HDLCError::MissingTradeChar**: Checks to make sure every frame escape character `fesc`
202/// is followed by either a `tfend` or a `tfesc`.
203/// * **HDLCError::MissingFirstFend**: Input vector is missing a first `SpecialChars::fend`
204/// * **HDLCError::MissingFinalFend**: Input vector is missing a final `SpecialChars::fend`
205///
206/// # Todo
207///
208/// Catch more errors, like an incomplete packet
209///
210/// # Example
211/// ```rust
212/// let chars = hdlc::SpecialChars::default();
213/// let input: Vec<u8> = vec![ 0x7E, 0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09, 0x7E];
214/// let op_vec = hdlc::decode(&input.to_vec(), chars);
215/// ```
216pub fn decode(input: &[u8], s_chars: SpecialChars) -> Result<Vec<u8>, HDLCError> {
217 // Safety check to make sure the special character values are all unique
218 let mut set = HashSet::new();
219 if !set.insert(s_chars.fend)
220 || !set.insert(s_chars.fesc)
221 || !set.insert(s_chars.tfend)
222 || !set.insert(s_chars.tfesc)
223 {
224 return Err(HDLCError::DuplicateSpecialChar);
225 }
226
227 // Predefine the vector for speed
228 let mut output: Vec<u8> = Vec::with_capacity(input.len());
229 // Iterator over the input that allows peeking
230 let mut input_iter = input.iter().peekable();
231 // Tracks whether input contains a final FEND
232 let mut has_final_fend = false;
233
234 // Verify input begins with a FEND
235 if input_iter.next() != Some(&s_chars.fend) {
236 return Err(HDLCError::MissingFirstFend);
237 }
238
239 // Loop over every byte of the message
240 while let Some(value) = input_iter.next() {
241 match *value {
242 // Handle a FESC
243 val if val == s_chars.fesc => match input_iter.next() {
244 Some(&val) if val == s_chars.tfend => output.push(s_chars.fend),
245 Some(&val) if val == s_chars.tfesc => output.push(s_chars.fesc),
246 _ => return Err(HDLCError::MissingTradeChar),
247 },
248 // Handle a FEND
249 val if val == s_chars.fend => {
250 if input_iter.peek().is_none() {
251 has_final_fend = true;
252 } else {
253 return Err(HDLCError::FendCharInData);
254 }
255 }
256 // Handle any other bytes
257 _ => output.push(*value),
258 }
259 }
260
261 // If the message had a final FEND, return the message
262 if has_final_fend {
263 Ok(output)
264 } else {
265 Err(HDLCError::MissingFinalFend)
266 }
267}
268
269/// Produces slice (`&[u8]`) unescaped (decoded) message without `FEND` characters.
270///
271/// # Inputs
272/// * **&mut [u8]**: A mutable slice of the bytes you want to decode
273/// * **SpecialChars**: The special characters you want to swap
274///
275/// # Output
276///
277/// * **Result<&[u8]>**: Decoded output message
278///
279/// # Error
280///
281/// * **HDLCError::DuplicateSpecialChar**: Checks special characters for duplicates, if any of
282/// the `SpecialChars` are duplicate, throw an error. Displays "Duplicate special character".
283/// * **HDLCError::FendCharInData**: Checks to make sure the full decoded message is the full
284/// length. Found the `SpecialChars::fend` inside the message.
285/// * **HDLCError::MissingTradeChar**: Checks to make sure every frame escape character `fesc`
286/// is followed by either a `tfend` or a `tfesc`.
287/// * **HDLCError::MissingFinalFend**: Input vector is missing a final `SpecialChars::fend`
288///
289/// # Todo
290///
291/// Catch more errors, like an incomplete packet
292///
293/// # Example
294/// ```rust
295/// let chars = hdlc::SpecialChars::default();
296/// let mut input = [ 0x7E, 0x01, 0x50, 0x00, 0x00, 0x00, 0x05, 0x80, 0x09, 0x7E];
297/// let op_vec = hdlc::decode_slice(&mut input, chars);
298/// ```
299pub fn decode_slice(input: &mut [u8], s_chars: SpecialChars) -> Result<&[u8], HDLCError> {
300 // Safety check to make sure the special character values are all unique
301 let mut set = HashSet::new();
302 if !set.insert(s_chars.fend)
303 || !set.insert(s_chars.fesc)
304 || !set.insert(s_chars.tfend)
305 || !set.insert(s_chars.tfesc)
306 {
307 return Err(HDLCError::DuplicateSpecialChar);
308 }
309
310 // Define the counting variables for proper loop functionality
311 let mut sync = 0;
312 let mut swap = 0;
313 let mut last_was_fesc = 0;
314 let input_length = input.len();
315
316 // Predefine the vector for iterator
317 let mut output: Vec<u8> = Vec::with_capacity(input_length);
318 output.extend_from_slice(input);
319
320 for (index, byte) in output.iter().enumerate() {
321 //println!("D={}, B={} S={} Output{:?}", index, byte, swap, input);
322 // Handle the special escape characters
323 if last_was_fesc > 0 {
324 if *byte == s_chars.tfesc {
325 swap += 1;
326 input[index - swap - 1] = s_chars.fesc;
327 } else if *byte == s_chars.tfend {
328 swap += 1;
329 input[index - swap - 1] = s_chars.fend;
330 } else {
331 return Err(HDLCError::MissingTradeChar);
332 }
333 last_was_fesc = 0
334 } else {
335 // Match based on the special characters, but struct fields are not patterns and cant match
336 if *byte == s_chars.fend {
337 // If we are already synced, this is the closing sync char
338 if sync > 0 {
339 // Check to make sure the full message was decoded
340 if (index + 1) < input_length {
341 return Err(HDLCError::FendCharInData);
342 }
343 // Minus 1 because indexing starts at 0
344 let end = index - swap - 1;
345 return Ok(&input[..end]);
346
347 // Todo: Maybe save for a 2nd message? I currently throw an error above
348 } else {
349 sync = 1;
350 }
351 } else if *byte == s_chars.fesc {
352 last_was_fesc = 1;
353 } else if sync > 0 {
354 // Minus 1 because indexing starts at 0
355 input[index - swap - 1] = *byte;
356 }
357 }
358 }
359
360 Err(HDLCError::MissingFinalFend)
361}
362
363/// A struct representing a reader for HDLC frames.
364/// It reads data from a source that implements the `std::io::Read` trait.
365/// The reader can be used to read frames from a stream of bytes.
366/// It will ignore the first bytes until the start of a frame.
367///
368/// /// # Fields
369/// * `reader`: A mutable reference to a reader that implements the `std::io::Read` trait.
370/// * `s_char`: The special characters used for HDLC encoding.
371/// * `rest`: A vector to store the remaining bytes after reading a frame.
372///
373/// # Example
374/// ```rust
375/// use hdlc::SpecialChars;
376/// use std::io::Cursor;
377/// use std::io::Read;
378/// use hdlc::FrameReader;
379///
380/// let chars = SpecialChars::default();
381/// let data: Vec<u8> = vec![ 0x7E, 0x01, 0x50, 0x00, 0x01, 0x7E, 0x7E, 0x11, 0x12, 0x13, 0x14, 0x7E];
382/// let mut frames: Vec<Vec<u8>> = vec![];
383/// let mut reader = Cursor::new(data);
384/// let mut hdlc_reader = FrameReader::new(&mut reader, chars);
385/// loop {
386/// match hdlc_reader.read_frame() {
387/// Some(data) => {
388/// frames.push(data);
389/// println!("got a frame {:?}", frames.last());
390/// }
391/// None => {
392/// println!("No frame");
393/// break;
394/// }
395/// }
396/// }
397/// assert_eq!(frames.len(), 2);
398/// assert_eq!(frames[0], vec![0x7E, 0x01, 0x50, 0x00, 0x01, 0x7E]);
399/// assert_eq!(frames[1], vec![0x7E, 0x11, 0x12, 0x13, 0x14, 0x7E]);
400///
401pub struct FrameReader<'a> {
402 /// Data source, can be any source that implements the std::io::Read trait
403 reader: &'a mut dyn Read,
404
405 /// List of HDLC special chars
406 s_char: SpecialChars,
407
408 /// The rest of received data
409 rest: Vec<u8>,
410}
411
412impl<'a> FrameReader<'a> {
413 /// Creates a new FrameReader instance.
414 ///
415 /// # Arguments
416 /// * `reader` - A mutable reference to a reader that implements the `std::io::Read` trait.
417 /// * `s_char` - The special characters used for HDLC encoding.
418 pub fn new(reader: &'a mut dyn Read, s_char: SpecialChars) -> Self {
419 Self {
420 reader,
421 s_char,
422 rest: Vec::new(),
423 }
424 }
425}
426
427impl FrameReader<'_> {
428 /// Reads a frame from the reader.
429 ///
430 /// The first bytes until the start of a frame are ignored.
431 ///
432 /// # Returns
433 /// * `Option<Vec<u8>>` - The frame read from the reader, or None if no more frames are available.
434 pub fn read_frame(&mut self) -> Option<Vec<u8>> {
435 let mut buffer = vec![0; 1024];
436 let bytes_read = self.reader.read(&mut buffer).ok().unwrap_or_default();
437 if bytes_read == 0 && self.rest.is_empty() {
438 // No more data to read
439 return None;
440 }
441
442 // Merge the rest with the new data
443 let mut data = self.rest.clone();
444 if bytes_read > 0 {
445 data.extend_from_slice(&buffer[..bytes_read]);
446 }
447
448 // Detect frame starting and ending with FEND
449 let mut in_frame = false;
450 let mut full_frame = false;
451 let mut frame: Vec<u8> = Vec::new();
452 let mut bytes_checked = 0;
453 for byte in data.iter() {
454 bytes_checked += 1;
455 if *byte == self.s_char.fend {
456 frame.push(*byte);
457
458 // End of a frame
459 if in_frame {
460 self.rest.clear();
461 full_frame = true;
462 break;
463 } else {
464 // If the next byte is also a fend byte, skip it
465 if let Some(next_byte) = data.get(frame.len()) {
466 if *next_byte == self.s_char.fend {
467 continue;
468 }
469 }
470 // The old bytes except of FEND should be removed
471 frame.drain(..frame.len().saturating_sub(1));
472 in_frame = true;
473 }
474 } else {
475 frame.push(*byte);
476 }
477 }
478
479 // Save the rest of the data for the next read
480 self.rest.extend_from_slice(&data[bytes_checked..]);
481
482 // If a frame is started and ended with FEND, return it, else its invalid
483 if full_frame {
484 Some(frame)
485 } else {
486 None
487 }
488 }
489}
490
491impl Iterator for FrameReader<'_> {
492 type Item = Vec<u8>;
493
494 fn next(&mut self) -> Option<Self::Item> {
495 self.read_frame()
496 }
497}
498
499#[derive(Debug, Error, PartialEq)]
500/// Common error for HDLC actions.
501pub enum HDLCError {
502 /// Catches duplicate special characters.
503 #[error("Caught a duplicate special character.")]
504 DuplicateSpecialChar,
505 /// Catches a random sync char in the data.
506 #[error("Caught a random sync char in the data.")]
507 FendCharInData,
508 /// Catches a random swap char, `fesc`, in the data with no `tfend` or `tfesc`.
509 #[error("Caught a random swap char in the data.")]
510 MissingTradeChar,
511 /// No first fend on the message.
512 #[error("Missing first FEND character.")]
513 MissingFirstFend,
514 /// No final fend on the message.
515 #[error("Missing final FEND character.")]
516 MissingFinalFend,
517}