1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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),
}
}
}