use crate::{END, ESC, ESC_END, ESC_ESC};
use std::io::{Read, Write};
#[derive(Debug)]
pub enum SlipError {
FramingError,
OversizedPacket,
EndOfStream,
ReadError(std::io::Error),
}
impl From<SlipError> for std::io::Error {
fn from(err: SlipError) -> std::io::Error {
match err {
SlipError::FramingError => {
std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", err))
}
SlipError::OversizedPacket => {
std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", err))
}
SlipError::EndOfStream => {
std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", err))
}
SlipError::ReadError(err) => err,
}
}
}
impl From<std::io::Error> for SlipError {
fn from(err: std::io::Error) -> Self {
SlipError::ReadError(err)
}
}
pub type SlipResult = std::result::Result<usize, self::SlipError>;
#[derive(Debug)]
enum State {
Normal,
Error,
Escape,
}
#[derive(Debug)]
pub struct SlipDecoder {
count: usize,
state: State,
}
impl SlipDecoder {
pub fn new() -> Self {
Self {
count: 0usize,
state: State::Normal,
}
}
fn push(&mut self, sink: &mut dyn Write, value: u8) -> self::SlipResult {
match sink.write(&[value]) {
Ok(len) => {
if len != 1 {
Err(SlipError::OversizedPacket)
} else {
self.count += 1;
Ok(1usize)
}
}
Err(error) => Err(error.into()),
}
}
pub fn decode(&mut self, source: &mut dyn Read, sink: &mut dyn Write) -> self::SlipResult {
for value in source.bytes() {
let value = value?;
match self.state {
State::Normal => match value {
END => {
if self.count > 0 {
let len = self.count;
self.count = 0usize;
return Ok(len);
}
}
ESC => {
self.state = State::Escape;
}
_ => {
self.push(sink, value)?;
}
},
State::Error => {
if value == END {
self.count = 0usize;
self.state = State::Normal;
}
}
State::Escape => match value {
ESC_END => {
self.push(sink, END)?;
self.state = State::Normal;
}
ESC_ESC => {
self.push(sink, ESC)?;
self.state = State::Normal;
}
_ => {
self.state = State::Error;
return Err(SlipError::FramingError);
}
},
}
}
Err(SlipError::EndOfStream)
}
}
impl Default for SlipDecoder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_decode() {
const INPUT: [u8; 2] = [0xc0, 0xc0];
let mut slip = SlipDecoder::new();
let mut buf: Vec<u8> = Vec::new();
let res = slip.decode(&mut INPUT.as_ref(), &mut buf);
assert!(res.is_err());
assert!(buf.is_empty());
}
#[test]
fn simple_decode() {
const INPUT: [u8; 7] = [0xc0, 0x01, 0x02, 0x03, 0x04, 0x05, 0xc0];
const DATA: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x05];
let mut slip = SlipDecoder::new();
let mut buf = [0u8; DATA.len()];
let len = slip.decode(&mut INPUT.as_ref(), &mut buf.as_mut()).unwrap();
assert_eq!(DATA.len(), len);
assert_eq!(DATA.len(), buf.len());
assert_eq!(&DATA, &buf);
}
#[test]
fn decode_esc_then_esc_end_sequence() {
const INPUT: [u8; 6] = [0xc0, 0x01, 0xdb, 0xdc, 0x03, 0xc0];
const DATA: [u8; 3] = [0x01, 0xc0, 0x03];
let mut slip = SlipDecoder::new();
let mut buf: Vec<u8> = Vec::new();
let len = slip.decode(&mut INPUT.as_ref(), &mut buf).unwrap();
assert_eq!(DATA.len(), len);
assert_eq!(DATA.len(), buf.len());
assert_eq!(&DATA, buf.as_slice());
}
#[test]
fn decode_esc_then_esc_esc_sequence() {
const INPUT: [u8; 6] = [0xc0, 0x01, 0xdb, 0xdd, 0x03, 0xc0];
const DATA: [u8; 3] = [0x01, 0xdb, 0x03];
let mut slip = SlipDecoder::new();
let mut buf: Vec<u8> = Vec::new();
let len = slip.decode(&mut INPUT.as_ref(), &mut buf).unwrap();
assert_eq!(DATA.len(), len);
assert_eq!(DATA.len(), buf.len());
assert_eq!(&DATA, buf.as_slice());
}
#[test]
fn multi_part_decode() {
const INPUT_1: [u8; 6] = [0xc0, 0x01, 0x02, 0x03, 0x04, 0x05];
const INPUT_2: [u8; 6] = [0x05, 0x06, 0x07, 0x08, 0x09, 0xc0];
const DATA: [u8; 10] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09];
let mut slip = SlipDecoder::new();
let mut buf: Vec<u8> = Vec::new();
{
let res = slip.decode(&mut INPUT_1.as_ref(), &mut buf);
assert!(res.is_err());
assert_eq!(5, buf.len());
}
{
let len = slip.decode(&mut INPUT_2.as_ref(), &mut buf).unwrap();
assert_eq!(DATA.len(), len);
assert_eq!(DATA.len(), buf.len());
assert_eq!(&DATA, buf.as_slice());
}
}
#[test]
fn compound_decode() {
const INPUT: [u8; 13] = [
0xc0, 0x01, 0x02, 0x03, 0x04, 0x05, 0xc0, 0x05, 0x06, 0x07, 0x08, 0x09, 0xc0,
];
const DATA_1: [u8; 5] = [0x01, 0x02, 0x03, 0x04, 0x05];
const DATA_2: [u8; 5] = [0x05, 0x06, 0x07, 0x08, 0x09];
let mut slip = SlipDecoder::new();
let reader: &mut dyn std::io::Read = &mut INPUT.as_ref();
{
let mut buf: Vec<u8> = Vec::new();
let len = slip.decode(reader, &mut buf).unwrap();
assert_eq!(DATA_1.len(), len);
assert_eq!(DATA_1.len(), buf.len());
assert_eq!(&DATA_1, buf.as_slice());
}
{
let mut buf: Vec<u8> = Vec::new();
let len = slip.decode(reader, &mut buf).unwrap();
assert_eq!(DATA_2.len(), len);
assert_eq!(DATA_2.len(), buf.len());
assert_eq!(&DATA_2, buf.as_slice());
}
}
}