use core::fmt::{Display, UpperHex};
use std::io::{self, Error};
use log::{debug, trace};
use serialport::SerialPort;
use crate::protocol::{ControlByte, Stuff};
use crate::types::RawFrame;
use crate::utils::HexSlice;
#[derive(Debug)]
pub struct Buffer<T> {
inner: T,
frame: RawFrame,
}
impl<T> Buffer<T> {
#[must_use]
pub const fn new(inner: T) -> Self {
Self {
inner,
frame: RawFrame::new(),
}
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T> Buffer<T>
where
T: SerialPort,
{
pub fn write_frame<F>(&mut self, frame: F) -> io::Result<()>
where
F: IntoIterator<Item = u8> + Display + UpperHex,
{
debug!("Writing frame: {frame}");
trace!("Frame: {frame:#04X}");
self.frame.clear();
self.frame.extend(frame);
trace!("Frame bytes: {:#04X}", HexSlice::new(&self.frame));
self.frame.stuff()?;
trace!("Stuffed bytes: {:#04X}", HexSlice::new(&self.frame));
self.frame
.push(ControlByte::Flag.into())
.map_err(|byte| Error::other(format!("Frame buffer overflow: {byte:#04X}")))?;
trace!("Writing bytes: {:#04X}", HexSlice::new(&self.frame));
self.inner.write_all(&self.frame)?;
self.inner.flush()
}
}