rust-mqtt 0.5.1

MQTT client for embedded and non-embedded environments
Documentation
use tokio_test::assert_ok;

#[cfg(feature = "alloc")]
use crate::buffer::AllocBuffer;
#[cfg(feature = "bump")]
use crate::buffer::BumpBuffer;
use crate::{
    buffer::BufferProvider,
    eio::Read,
    header::FixedHeader,
    io::{
        err::ReadError,
        read::{BodyReader, Readable},
    },
    packet::RxPacket,
    test::read::SliceReader,
    types::VarByteInt,
};

macro_rules! decode {
    ($t:ty, $remaining_len:literal, $bytes:expr) => {{
        const LEN: usize = ($bytes).len();
        const REMAINING_LEN: usize = ($remaining_len);

        let buffer: &mut [u8; LEN] = std::boxed::Box::leak(std::boxed::Box::new([0u8; LEN]));

        crate::test::rx::decode_packet::<$t, _, REMAINING_LEN>(($bytes), buffer).await
    }};
}

impl<R: Read> Readable<R> for FixedHeader {
    async fn read(net: &mut R) -> Result<Self, ReadError<R::Error>> {
        let type_and_flags = u8::read(net).await?;
        let remaining_len = VarByteInt::read(net).await?;
        Ok(Self {
            type_and_flags,
            remaining_len,
        })
    }
}

pub async fn decode_packet<'a, T: RxPacket<'a>, const N: usize, const REMAINING_LEN: usize>(
    bytes: [u8; N],
    buffer: &'a mut [u8],
) -> T {
    let mut reader = SliceReader::new(&bytes);

    let mut buffer = create_buffer(buffer);

    let result = FixedHeader::read(&mut reader).await;
    let header = assert_ok!(result);

    let packet_type = assert_ok!(header.packet_type());
    assert_eq!(packet_type, T::PACKET_TYPE, "Packet type not matching");

    assert_eq!(
        header.remaining_len.size(),
        REMAINING_LEN,
        "Remaining length not matching"
    );

    let reader = BodyReader::new(&mut reader, &mut buffer, REMAINING_LEN);
    let result = T::receive(&header, reader).await;
    let packet = assert_ok!(result);

    packet
}

#[allow(unused_variables)]
fn create_buffer(buffer: &mut [u8]) -> impl BufferProvider<'_> {
    #[cfg(feature = "bump")]
    {
        BumpBuffer::new(buffer)
    }
    #[cfg(feature = "alloc")]
    {
        AllocBuffer
    }

    #[cfg(not(any(feature = "bump", feature = "alloc")))]
    {
        buffer::FailingBuffer
    }
}

#[cfg(not(any(feature = "bump", feature = "alloc")))]
mod buffer {
    use crate::buffer::BufferProvider;

    pub struct FailingBuffer;
    impl<'a> BufferProvider<'a> for FailingBuffer {
        type Buffer = &'a mut [u8];
        type ProvisionError = ();

        fn provide_buffer(&mut self, _: usize) -> Result<Self::Buffer, Self::ProvisionError> {
            Err(())
        }
    }
}

pub(crate) use decode;