minimq 0.12.0

An MQTT5 client
Documentation
use crate::{
    ConfigError, QoS, Retain,
    properties::{Properties, Property, PropertyContext},
    wire::{BinaryData, Utf8String},
};
use heapless::String;

const TOPIC_CAPACITY: usize = 128;
type TopicString = String<TOPIC_CAPACITY>;

fn validate_will_properties(properties: &[Property<'_>]) -> Result<(), ConfigError> {
    for property in properties {
        if !property.is_valid_for(PropertyContext::Will) {
            return Err(ConfigError::InvalidConfig);
        }
    }
    Ok(())
}

/// MQTT will message.
#[derive(Debug, Clone, PartialEq)]
pub struct Will<'a> {
    topic: TopicString,
    data: &'a [u8],
    qos: QoS,
    retained: Retain,
    properties: &'a [Property<'a>],
}

impl<'a> Will<'a> {
    /// Construct a will.
    ///
    /// Only MQTT v5 properties valid on will messages are accepted.
    pub fn new(
        topic: &str,
        data: &'a [u8],
        properties: &'a [Property<'a>],
    ) -> Result<Self, ConfigError> {
        validate_will_properties(properties)?;
        let topic = topic.try_into().map_err(|_| ConfigError::TopicTooLong)?;

        Ok(Self {
            topic,
            data,
            properties,
            qos: QoS::AtMostOnce,
            retained: Retain::NotRetained,
        })
    }

    /// Mark the will as retained.
    pub fn retained(mut self) -> Self {
        self.retained = Retain::Retained;
        self
    }

    /// Set the will QoS.
    pub fn qos(mut self, qos: QoS) -> Self {
        self.qos = qos;
        self
    }

    pub(crate) fn retained_flag(&self) -> Retain {
        self.retained
    }

    pub(crate) fn qos_level(&self) -> QoS {
        self.qos
    }
}

impl serde::Serialize for Will<'_> {
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        use serde::ser::SerializeStruct;

        let mut item = serializer.serialize_struct("Will", 0)?;
        item.serialize_field("properties", &Properties::from_slice(self.properties))?;
        item.serialize_field("topic", &Utf8String(self.topic.as_str()))?;
        item.serialize_field("data", &BinaryData(self.data))?;
        item.end()
    }
}