rust-mqtt 0.5.1

MQTT client for embedded and non-embedded environments
Documentation
use crate::{
    eio::Write,
    fmt::unreachable,
    io::err::WriteError,
    types::{MqttBinary, MqttString, TopicFilter, TopicName, VarByteInt},
};

pub trait Writable {
    fn written_len(&self) -> usize;
    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>>;
}

macro_rules! wlen {
    ( $W:ty ) => {
        <$W>::default().written_len()
    };
}

impl<T: Writable> Writable for Option<T> {
    fn written_len(&self) -> usize {
        self.as_ref().map(Writable::written_len).unwrap_or_default()
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        match self {
            Some(t) => t.write(write).await,
            None => Ok(()),
        }
    }
}

impl Writable for [u8] {
    fn written_len(&self) -> usize {
        self.len()
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        let mut slice = self;
        while !slice.is_empty() {
            match write.write(slice).await? {
                0 => return Err(WriteError::WriteZero),
                n => slice = &slice[n..],
            }
        }
        Ok(())
    }
}

macro_rules! int_write_impl {
    ($int:ty) => {
        impl Writable for $int {
            fn written_len(&self) -> usize {
                size_of::<$int>()
            }
            async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
                self.to_be_bytes().write(write).await
            }
        }
    };
}

int_write_impl!(u8);
int_write_impl!(u16);
int_write_impl!(u32);

impl Writable for bool {
    fn written_len(&self) -> usize {
        wlen!(u8)
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        <Self as Into<u8>>::into(*self).write(write).await
    }
}
impl Writable for VarByteInt {
    fn written_len(&self) -> usize {
        match self.value() {
            0..=127 => 1,
            128..=16_383 => 2,
            16_384..=2_097_151 => 3,
            2_097_152..=Self::MAX_ENCODABLE => 4,
            _ => unreachable!(
                "Invariant, never occurs if VarByteInts are generated using From, TryFrom and new"
            ),
        }
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        let mut x = self.value();
        let mut encoded_byte: u8;

        loop {
            encoded_byte = (x % 128) as u8;
            x /= 128;

            if x > 0 {
                encoded_byte |= 128;
            }
            encoded_byte.write(write).await?;

            if x == 0 {
                return Ok(());
            }
        }
    }
}
impl Writable for MqttBinary<'_> {
    fn written_len(&self) -> usize {
        self.0.len() + wlen!(u16)
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        let len = self.len();
        len.write(write).await?;

        self.0.write(write).await?;

        Ok(())
    }
}
impl Writable for MqttString<'_> {
    fn written_len(&self) -> usize {
        self.0.written_len()
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        self.0.write(write).await
    }
}
impl Writable for TopicName<'_> {
    fn written_len(&self) -> usize {
        self.as_ref().written_len()
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        self.as_ref().write(write).await
    }
}
impl Writable for TopicFilter<'_> {
    fn written_len(&self) -> usize {
        self.as_ref().written_len()
    }

    async fn write<W: Write>(&self, write: &mut W) -> Result<(), WriteError<W::Error>> {
        self.as_ref().write(write).await
    }
}

pub(crate) use wlen;