Skip to main content

rust_mqtt/client/options/
publish.rs

1use const_fn::const_fn;
2
3use crate::types::{MqttBinary, MqttString, QoS, TopicName};
4
5/// Options for a publication.
6#[derive(Debug, Clone)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8pub struct Options<'p> {
9    /// The quality of service that the message is published with to the server.
10    /// The quality of service level used by the server to send this publication
11    /// to subscribed clients is the minimum of this value and the quality of service
12    /// value of the receiving client's subscription.
13    pub qos: QoS,
14
15    /// Depicts the value of the retain flag in the PUBLISH packet.
16    /// If set to 1, the server should retain the message on this topic.
17    /// Retained messages with quality of service 0 can be discarded
18    /// at any time by the server.
19    pub retain: bool,
20
21    /// The topic that the message is published on. The topic can be referenced over
22    /// an existing topic alias mapping or by specifying the topic name and optionally
23    /// mapping a topic alias to it.
24    pub topic: TopicReference<'p>,
25
26    /// Indicates whether the message is valid UTF-8. If [`None`], there is no statement
27    /// about the UTF-8 character of the message.
28    pub payload_format_indicator: Option<bool>,
29
30    /// The message expiry interval in seconds of this application message. After this
31    /// interval has passed, the server cannot publish this message onward to subscribers.
32    /// If set to [`None`], the message does not expire and the message expiry interval
33    /// property is omitted on the network.
34    pub message_expiry_interval: Option<u32>,
35
36    /// The topic on which the receiver should publish the response.
37    pub response_topic: Option<TopicName<'p>>,
38
39    /// Arbitrary binary data which the receiver should attach in the response to associate
40    /// their response with this request.
41    pub correlation_data: Option<MqttBinary<'p>>,
42
43    /// The custom content type of the message.
44    pub content_type: Option<MqttString<'p>>,
45}
46
47impl<'p> Options<'p> {
48    /// Creates options with values coherent to the [`Default`] implementations of the fields and
49    /// [`QoS::AtMostOnce`].
50    #[must_use]
51    pub const fn new(topic: TopicReference<'p>) -> Options<'p> {
52        Options {
53            qos: QoS::AtMostOnce,
54            retain: false,
55            topic,
56            payload_format_indicator: None,
57            message_expiry_interval: None,
58            response_topic: None,
59            correlation_data: None,
60            content_type: None,
61        }
62    }
63
64    /// Sets the Quality of Service level.
65    #[must_use]
66    pub const fn qos(mut self, qos: QoS) -> Self {
67        self.qos = qos;
68        self
69    }
70    /// Sets the Quality of Service level to 1 (At Least Once).
71    #[must_use]
72    pub const fn at_least_once(self) -> Self {
73        self.qos(QoS::AtLeastOnce)
74    }
75    /// Sets the Quality of Service level to 1 (Exactly Once).
76    #[must_use]
77    pub const fn exactly_once(self) -> Self {
78        self.qos(QoS::ExactlyOnce)
79    }
80    /// Sets the retain flag to true.
81    #[must_use]
82    pub const fn retain(mut self) -> Self {
83        self.retain = true;
84        self
85    }
86    /// Sets the payload format indicator property.
87    #[must_use]
88    pub const fn payload_format_indicator(mut self, is_payload_utf8: bool) -> Self {
89        self.payload_format_indicator = Some(is_payload_utf8);
90        self
91    }
92    /// Sets the message expiry interval in seconds.
93    #[must_use]
94    pub const fn message_expiry_interval(mut self, seconds: u32) -> Self {
95        self.message_expiry_interval = Some(seconds);
96        self
97    }
98    /// Marks the publication as a request by setting the response topic property.
99    #[const_fn(cfg(not(feature = "alloc")))]
100    #[must_use]
101    pub const fn response_topic(mut self, topic: TopicName<'p>) -> Self {
102        self.response_topic = Some(topic);
103        self
104    }
105    /// Sets the correlation data property in the request.
106    #[const_fn(cfg(not(feature = "alloc")))]
107    #[must_use]
108    pub const fn correlation_data(mut self, data: MqttBinary<'p>) -> Self {
109        self.correlation_data = Some(data);
110        self
111    }
112    /// Sets the content type property.
113    #[const_fn(cfg(not(feature = "alloc")))]
114    #[must_use]
115    pub const fn content_type(mut self, content_type: MqttString<'p>) -> Self {
116        self.content_type = Some(content_type);
117        self
118    }
119}
120
121/// The options for specifying which topic to publish to. Topic aliases only last for the
122/// duration of a single network connection and not necessarily until the session end.
123///
124/// Topic aliases must not be 0
125#[derive(Debug, Clone, PartialEq, Eq)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127pub enum TopicReference<'t> {
128    /// Publish to the inner topic name without creating an alias.
129    Name(TopicName<'t>),
130
131    /// Publish to an already mapped topic alias. The alias must have been defined earlier
132    /// in the network connection.
133    Alias(u16),
134
135    /// Create a new topic alias or replace an existing topic alias.
136    /// The alias lasts until the end of the network connection.
137    Mapping(TopicName<'t>, u16),
138}
139
140impl<'t> TopicReference<'t> {
141    pub(crate) fn alias(&self) -> Option<u16> {
142        match self {
143            Self::Name(_) => None,
144            Self::Alias(alias) => Some(*alias),
145            Self::Mapping(_, alias) => Some(*alias),
146        }
147    }
148    pub(crate) fn topic_name(&self) -> Option<&TopicName<'t>> {
149        match self {
150            Self::Name(topic_name) => Some(topic_name),
151            Self::Alias(_) => None,
152            Self::Mapping(topic_name, _) => Some(topic_name),
153        }
154    }
155
156    /// Delegates to [`crate::Bytes::as_borrowed`].
157    #[must_use]
158    pub fn as_borrowed(&'t self) -> Self {
159        match self {
160            Self::Name(topic_name) => Self::Name(topic_name.as_borrowed()),
161            Self::Alias(alias) => Self::Alias(*alias),
162            Self::Mapping(topic_name, alias) => Self::Mapping(topic_name.as_borrowed(), *alias),
163        }
164    }
165}