#![deny(missing_docs)]
use thiserror::Error;
use std::collections::HashSet;
use std::default::Default;
use std::io::Read;
#[derive(Debug, Copy, Clone)]
pub struct SpecialChars {
pub fend: u8,
pub fesc: u8,
pub tfend: u8,
pub tfesc: u8,
}
impl Default for SpecialChars {
fn default() -> SpecialChars {
SpecialChars {
fend: 0x7E,
fesc: 0x7D,
tfend: 0x5E,
tfesc: 0x5D,
}
}
}
impl SpecialChars {
pub fn new(fend: u8, fesc: u8, tfend: u8, tfesc: u8) -> SpecialChars {
SpecialChars {
fend,
fesc,
tfend,
tfesc,
}
}
}
pub fn encode(data: &[u8], s_chars: SpecialChars) -> Result<Vec<u8>, HDLCError> {
let mut set = HashSet::new();
if !set.insert(s_chars.fend)
|| !set.insert(s_chars.fesc)
|| !set.insert(s_chars.tfend)
|| !set.insert(s_chars.tfesc)
{
return Err(HDLCError::DuplicateSpecialChar);
}
let mut output = Vec::with_capacity(data.len() * 2);
let input_iter = data.iter();
output.push(s_chars.fend);
for value in input_iter {
match *value {
val if val == s_chars.fesc => {
output.push(s_chars.fesc);
output.push(s_chars.tfesc);
}
val if val == s_chars.fend => {
output.push(s_chars.fesc);
output.push(s_chars.tfend);
}
_ => output.push(*value),
}
}
output.push(s_chars.fend);
Ok(output)
}
pub fn decode(input: &[u8], s_chars: SpecialChars) -> Result<Vec<u8>, HDLCError> {
let mut set = HashSet::new();
if !set.insert(s_chars.fend)
|| !set.insert(s_chars.fesc)
|| !set.insert(s_chars.tfend)
|| !set.insert(s_chars.tfesc)
{
return Err(HDLCError::DuplicateSpecialChar);
}
let mut output: Vec<u8> = Vec::with_capacity(input.len());
let mut input_iter = input.iter().peekable();
let mut has_final_fend = false;
if input_iter.next() != Some(&s_chars.fend) {
return Err(HDLCError::MissingFirstFend);
}
while let Some(value) = input_iter.next() {
match *value {
val if val == s_chars.fesc => match input_iter.next() {
Some(&val) if val == s_chars.tfend => output.push(s_chars.fend),
Some(&val) if val == s_chars.tfesc => output.push(s_chars.fesc),
_ => return Err(HDLCError::MissingTradeChar),
},
val if val == s_chars.fend => {
if input_iter.peek().is_none() {
has_final_fend = true;
} else {
return Err(HDLCError::FendCharInData);
}
}
_ => output.push(*value),
}
}
if has_final_fend {
Ok(output)
} else {
Err(HDLCError::MissingFinalFend)
}
}
pub fn decode_slice(input: &mut [u8], s_chars: SpecialChars) -> Result<&[u8], HDLCError> {
let mut set = HashSet::new();
if !set.insert(s_chars.fend)
|| !set.insert(s_chars.fesc)
|| !set.insert(s_chars.tfend)
|| !set.insert(s_chars.tfesc)
{
return Err(HDLCError::DuplicateSpecialChar);
}
let mut sync = 0;
let mut swap = 0;
let mut last_was_fesc = 0;
let input_length = input.len();
let mut output: Vec<u8> = Vec::with_capacity(input_length);
output.extend_from_slice(input);
for (index, byte) in output.iter().enumerate() {
if last_was_fesc > 0 {
if *byte == s_chars.tfesc {
swap += 1;
input[index - swap - 1] = s_chars.fesc;
} else if *byte == s_chars.tfend {
swap += 1;
input[index - swap - 1] = s_chars.fend;
} else {
return Err(HDLCError::MissingTradeChar);
}
last_was_fesc = 0
} else {
if *byte == s_chars.fend {
if sync > 0 {
if (index + 1) < input_length {
return Err(HDLCError::FendCharInData);
}
let end = index - swap - 1;
return Ok(&input[..end]);
} else {
sync = 1;
}
} else if *byte == s_chars.fesc {
last_was_fesc = 1;
} else if sync > 0 {
input[index - swap - 1] = *byte;
}
}
}
Err(HDLCError::MissingFinalFend)
}
pub struct FrameReader<'a> {
reader: &'a mut dyn Read,
s_char: SpecialChars,
rest: Vec<u8>,
}
impl<'a> FrameReader<'a> {
pub fn new(reader: &'a mut dyn Read, s_char: SpecialChars) -> Self {
Self {
reader,
s_char,
rest: Vec::new(),
}
}
}
impl FrameReader<'_> {
pub fn read_frame(&mut self) -> Option<Vec<u8>> {
let mut buffer = vec![0; 1024];
let bytes_read = self.reader.read(&mut buffer).ok().unwrap_or_default();
if bytes_read == 0 && self.rest.is_empty() {
return None;
}
let mut data = self.rest.clone();
if bytes_read > 0 {
data.extend_from_slice(&buffer[..bytes_read]);
}
let mut in_frame = false;
let mut full_frame = false;
let mut frame: Vec<u8> = Vec::new();
let mut bytes_checked = 0;
for byte in data.iter() {
bytes_checked += 1;
if *byte == self.s_char.fend {
frame.push(*byte);
if in_frame {
self.rest.clear();
full_frame = true;
break;
} else {
if let Some(next_byte) = data.get(frame.len()) {
if *next_byte == self.s_char.fend {
continue;
}
}
frame.drain(..frame.len().saturating_sub(1));
in_frame = true;
}
} else {
frame.push(*byte);
}
}
self.rest.extend_from_slice(&data[bytes_checked..]);
if full_frame {
Some(frame)
} else {
None
}
}
}
impl Iterator for FrameReader<'_> {
type Item = Vec<u8>;
fn next(&mut self) -> Option<Self::Item> {
self.read_frame()
}
}
#[derive(Debug, Error, PartialEq)]
pub enum HDLCError {
#[error("Caught a duplicate special character.")]
DuplicateSpecialChar,
#[error("Caught a random sync char in the data.")]
FendCharInData,
#[error("Caught a random swap char in the data.")]
MissingTradeChar,
#[error("Missing first FEND character.")]
MissingFirstFend,
#[error("Missing final FEND character.")]
MissingFinalFend,
}