use core::fmt::Debug;
use std::io;
use ashv2::{MAX_PAYLOAD_SIZE, Payload, Proxy};
use le_stream::ToLeStream;
use log::trace;
use crate::frame::Header;
use crate::{Error, MAX_HEADER_SIZE, MAX_PARAMETER_SIZE};
#[derive(Debug)]
pub struct Encoder {
proxy: Proxy,
header: heapless::Vec<u8, MAX_HEADER_SIZE>,
parameters: heapless::Vec<u8, MAX_PARAMETER_SIZE>,
}
impl Encoder {
pub const fn new(proxy: Proxy) -> Self {
Self {
proxy,
header: heapless::Vec::new(),
parameters: heapless::Vec::new(),
}
}
pub async fn send<P>(&mut self, header: Header, parameters: P) -> Result<(), Error>
where
P: Debug + ToLeStream,
{
self.header.clear();
self.parameters.clear();
match header {
Header::Legacy(header) => self.header.extend(header.to_le_stream()),
Header::Extended(header) => self.header.extend(header.to_le_stream()),
}
trace!("Sending header: {:#04X?}", self.header);
trace!("Sending parameters (type): {parameters:?}");
self.parameters.extend(parameters.to_le_stream());
trace!("Sending parameters (bytes): {:#04X?}", self.parameters);
if self.parameters.is_empty() {
self.send_chunk(&[]).await?;
}
trace!("Sending chunks of {MAX_PAYLOAD_SIZE} bytes.");
for chunk in self
.parameters
.chunks(MAX_PAYLOAD_SIZE.saturating_sub(self.header.len()))
{
self.send_chunk(chunk).await?;
}
Ok(())
}
async fn send_chunk(&self, chunk: &[u8]) -> io::Result<()> {
let mut payload = Payload::new();
payload
.extend_from_slice(&self.header)
.map_err(io::Error::other)?;
payload.extend_from_slice(chunk).map_err(io::Error::other)?;
trace!("Sending chunk: {payload:#04X?}");
self.proxy.send(payload).await
}
}