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}