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}