use crate::constants::*;
use crate::errors::*;
use std::borrow::Cow;
use std::io::{Read, Write};
#[derive(Debug)]
pub(crate) enum Command<'a> {
DataFrame(Cow<'a, [u8]>),
TxDelay(u8),
Return,
}
impl<'a> Command<'a> {
pub fn owned_frame(data: Vec<u8>) -> Self {
Self::DataFrame(Cow::Owned(data))
}
pub fn borrowed_frame(data: &'a [u8]) -> Self {
Self::DataFrame(Cow::Borrowed(data))
}
pub fn write<W: Write>(&self, port: u8, writer: &mut W) -> std::io::Result<usize> {
assert!(port < 16);
let port = port << 4;
let mut count = 0;
count += writer.write(&[FEND])?;
match self {
Self::DataFrame(data) => {
count += writer.write(&[DATA_FRAME | port])?;
for &b in data.as_ref() {
count += match b {
FEND => writer.write(&[FESC, TFEND])?,
FESC => writer.write(&[FESC, TFESC])?,
_ => writer.write(&[b])?,
}
}
}
Self::TxDelay(delay) => {
count += writer.write(&[TX_DELAY | port])?;
count += writer.write(&[*delay])?;
}
Self::Return => {
count += writer.write(&[RETURN])?;
}
}
count += writer.write(&[FEND])?;
Ok(count)
}
pub fn read<R: Read>(reader: &mut R) -> Result<(u8, Self), ReadError> {
let mut buf = [0];
reader.read_exact(&mut buf)?;
if buf != [0xC0] {
return Err(ReadError::MalformedData);
}
while buf == [0xC0] {
reader.read_exact(&mut buf)?;
}
let port = (buf[0] & 0xF0) >> 4;
let code = buf[0] & 0x0F;
if code != 0x00 {
return Err(ReadError::MalformedData);
}
let mut data = vec![];
reader.read_exact(&mut buf)?;
while buf[0] != 0xC0 {
let b = buf[0];
if b == FESC {
reader.read_exact(&mut buf)?;
match buf[0] {
TFEND => {
data.push(FEND);
}
TFESC => {
data.push(FESC);
}
_ => return Err(ReadError::MalformedData),
}
} else {
data.push(b);
}
reader.read_exact(&mut buf)?;
}
Ok((port, Self::owned_frame(data)))
}
}