rust-mqtt 0.5.1

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

use crate::types::{MqttBinary, MqttString, QoS, TopicName};

/// Options for a publication.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Options<'p> {
    /// The quality of service that the message is published with to the server.
    /// The quality of service level used by the server to send this publication
    /// to subscribed clients is the minimum of this value and the quality of service
    /// value of the receiving client's subscription.
    pub qos: QoS,

    /// Depicts the value of the retain flag in the PUBLISH packet.
    /// If set to 1, the server should retain the message on this topic.
    /// Retained messages with quality of service 0 can be discarded
    /// at any time by the server.
    pub retain: bool,

    /// The topic that the message is published on. The topic can be referenced over
    /// an existing topic alias mapping or by specifying the topic name and optionally
    /// mapping a topic alias to it.
    pub topic: TopicReference<'p>,

    /// Indicates whether the message is valid UTF-8. If [`None`], there is no statement
    /// about the UTF-8 character of the message.
    pub payload_format_indicator: Option<bool>,

    /// The message expiry interval in seconds of this application message. After this
    /// interval has passed, the server cannot publish this message onward to subscribers.
    /// If set to [`None`], the message does not expire and the message expiry interval
    /// property is omitted on the network.
    pub message_expiry_interval: Option<u32>,

    /// The topic on which the receiver should publish the response.
    pub response_topic: Option<TopicName<'p>>,

    /// Arbitrary binary data which the receiver should attach in the response to associate
    /// their response with this request.
    pub correlation_data: Option<MqttBinary<'p>>,

    /// The custom content type of the message.
    pub content_type: Option<MqttString<'p>>,
}

impl<'p> Options<'p> {
    /// Creates options with values coherent to the [`Default`] implementations of the fields and
    /// [`QoS::AtMostOnce`].
    #[must_use]
    pub const fn new(topic: TopicReference<'p>) -> Options<'p> {
        Options {
            qos: QoS::AtMostOnce,
            retain: false,
            topic,
            payload_format_indicator: None,
            message_expiry_interval: None,
            response_topic: None,
            correlation_data: None,
            content_type: None,
        }
    }

    /// Sets the Quality of Service level.
    #[must_use]
    pub const fn qos(mut self, qos: QoS) -> Self {
        self.qos = qos;
        self
    }
    /// Sets the Quality of Service level to 1 (At Least Once).
    #[must_use]
    pub const fn at_least_once(self) -> Self {
        self.qos(QoS::AtLeastOnce)
    }
    /// Sets the Quality of Service level to 1 (Exactly Once).
    #[must_use]
    pub const fn exactly_once(self) -> Self {
        self.qos(QoS::ExactlyOnce)
    }
    /// Sets the retain flag to true.
    #[must_use]
    pub const fn retain(mut self) -> Self {
        self.retain = true;
        self
    }
    /// Sets the payload format indicator property.
    #[must_use]
    pub const fn payload_format_indicator(mut self, is_payload_utf8: bool) -> Self {
        self.payload_format_indicator = Some(is_payload_utf8);
        self
    }
    /// Sets the message expiry interval in seconds.
    #[must_use]
    pub const fn message_expiry_interval(mut self, seconds: u32) -> Self {
        self.message_expiry_interval = Some(seconds);
        self
    }
    /// Marks the publication as a request by setting the response topic property.
    #[const_fn(cfg(not(feature = "alloc")))]
    #[must_use]
    pub const fn response_topic(mut self, topic: TopicName<'p>) -> Self {
        self.response_topic = Some(topic);
        self
    }
    /// Sets the correlation data property in the request.
    #[const_fn(cfg(not(feature = "alloc")))]
    #[must_use]
    pub const fn correlation_data(mut self, data: MqttBinary<'p>) -> Self {
        self.correlation_data = Some(data);
        self
    }
    /// Sets the content type property.
    #[const_fn(cfg(not(feature = "alloc")))]
    #[must_use]
    pub const fn content_type(mut self, content_type: MqttString<'p>) -> Self {
        self.content_type = Some(content_type);
        self
    }
}

/// The options for specifying which topic to publish to. Topic aliases only last for the
/// duration of a single network connection and not necessarily until the session end.
///
/// Topic aliases must not be 0
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TopicReference<'t> {
    /// Publish to the inner topic name without creating an alias.
    Name(TopicName<'t>),

    /// Publish to an already mapped topic alias. The alias must have been defined earlier
    /// in the network connection.
    Alias(u16),

    /// Create a new topic alias or replace an existing topic alias.
    /// The alias lasts until the end of the network connection.
    Mapping(TopicName<'t>, u16),
}

impl<'t> TopicReference<'t> {
    pub(crate) fn alias(&self) -> Option<u16> {
        match self {
            Self::Name(_) => None,
            Self::Alias(alias) => Some(*alias),
            Self::Mapping(_, alias) => Some(*alias),
        }
    }
    pub(crate) fn topic_name(&self) -> Option<&TopicName<'t>> {
        match self {
            Self::Name(topic_name) => Some(topic_name),
            Self::Alias(_) => None,
            Self::Mapping(topic_name, _) => Some(topic_name),
        }
    }

    /// Delegates to [`crate::Bytes::as_borrowed`].
    #[must_use]
    pub fn as_borrowed(&'t self) -> Self {
        match self {
            Self::Name(topic_name) => Self::Name(topic_name.as_borrowed()),
            Self::Alias(alias) => Self::Alias(*alias),
            Self::Mapping(topic_name, alias) => Self::Mapping(topic_name.as_borrowed(), *alias),
        }
    }
}