use crate::{write_variable_byte_integer, CtrlPkt, Error};
use core::{cmp::min, marker::PhantomData, mem::size_of};
use w5500_hl::{
io::{Read, Seek, SeekFrom, Write},
Error as HlError,
};
pub fn send_publish<E, Writer: Write<E>>(
mut writer: Writer,
topic: &str,
payload: &[u8],
) -> Result<(), HlError<E>> {
let topic_len: u16 = topic.len().try_into().unwrap_or(u16::MAX);
let payload_len: u16 = payload.len().try_into().unwrap_or(u16::MAX);
const TOPIC_LEN_LEN: u32 = size_of::<u16>() as u32;
const PROPERTY_LEN: u32 = size_of::<u8>() as u32;
let remaining_len: u32 =
TOPIC_LEN_LEN + u32::from(topic_len) + PROPERTY_LEN + u32::from(payload_len);
writer.write_all(&[
(CtrlPkt::PUBLISH as u8) << 4,
])?;
write_variable_byte_integer(&mut writer, remaining_len)?;
writer.write_all(&topic_len.to_be_bytes())?;
writer.write_all(&topic.as_bytes()[..topic_len.into()])?;
writer.write_all(&[0])?; writer.write_all(&payload[..payload_len.into()])?;
writer.send()?;
Ok(())
}
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PublishReader<E, Reader: Read<E> + Seek<E>> {
pub(crate) reader: Reader,
pub(crate) topic_len: u16,
pub(crate) topic_idx: u16,
pub(crate) payload_len: u16,
pub(crate) payload_idx: u16,
pub(crate) _reader_error: PhantomData<E>,
}
impl<E, Reader: Read<E> + Seek<E>> PublishReader<E, Reader> {
#[inline]
pub fn topic_len(&self) -> u16 {
self.topic_len
}
#[inline]
pub fn payload_len(&self) -> u16 {
self.payload_len
}
pub fn read_topic(&mut self, buf: &mut [u8]) -> Result<u16, Error<E>> {
self.reader
.seek(SeekFrom::Start(self.topic_idx))
.map_err(Error::map_w5500)?;
let read_len: u16 = min(buf.len().try_into().unwrap_or(u16::MAX), self.topic_len);
self.reader
.read_exact(&mut buf[..read_len.into()])
.map_err(Error::map_w5500)?;
Ok(read_len)
}
pub fn read_payload(&mut self, buf: &mut [u8]) -> Result<u16, Error<E>> {
self.reader
.seek(SeekFrom::Start(self.payload_idx))
.map_err(Error::map_w5500)?;
let read_len: u16 = min(buf.len().try_into().unwrap_or(u16::MAX), self.payload_len);
self.reader
.read_exact(&mut buf[..read_len.into()])
.map_err(Error::map_w5500)?;
Ok(read_len)
}
#[inline]
pub fn done(mut self) -> Result<(), Error<E>> {
self.reader
.seek(SeekFrom::Start(self.payload_idx + self.payload_len))
.map_err(Error::map_w5500)?;
self.reader.done()?;
Ok(())
}
}