minimq/
will.rs

1use crate::{
2    properties::{Property, PropertyIdentifier},
3    types::{BinaryData, Properties, Utf8String},
4    varint::Varint,
5    ProtocolError, QoS, Retain,
6};
7
8use serde::Serialize;
9
10#[derive(Debug)]
11pub struct Will<'a> {
12    topic: &'a str,
13    data: &'a [u8],
14    qos: QoS,
15    retained: Retain,
16    properties: &'a [Property<'a>],
17}
18
19#[derive(Serialize)]
20struct WillMessage<'a> {
21    properties: Properties<'a>,
22    topic: Utf8String<'a>,
23    data: BinaryData<'a>,
24}
25
26impl<'a> Will<'a> {
27    /// Construct a new will message.
28    ///
29    /// # Args
30    /// * `topic` - The topic to send the message on
31    /// * `data` - The message to transmit
32    /// * `properties` - Any properties to send with the will message.
33    pub fn new(
34        topic: &'a str,
35        data: &'a [u8],
36        properties: &'a [Property<'a>],
37    ) -> Result<Self, ProtocolError> {
38        // Check that the input properties are valid for a will.
39        for property in properties {
40            match property.into() {
41                PropertyIdentifier::WillDelayInterval
42                | PropertyIdentifier::PayloadFormatIndicator
43                | PropertyIdentifier::MessageExpiryInterval
44                | PropertyIdentifier::ContentType
45                | PropertyIdentifier::ResponseTopic
46                | PropertyIdentifier::CorrelationData
47                | PropertyIdentifier::UserProperty => {}
48                _ => return Err(ProtocolError::InvalidProperty),
49            }
50        }
51
52        Ok(Self {
53            topic,
54            data,
55            properties,
56            qos: QoS::AtMostOnce,
57            retained: Retain::NotRetained,
58        })
59    }
60
61    /// Serialize the will contents into a flattened, borrowed buffer.
62    pub(crate) fn serialize<'b>(
63        &self,
64        buf: &'b mut [u8],
65    ) -> Result<SerializedWill<'b>, crate::ser::Error> {
66        let message = WillMessage {
67            topic: Utf8String(self.topic),
68            properties: Properties::Slice(self.properties),
69            data: BinaryData(self.data),
70        };
71
72        let mut serializer = crate::ser::MqttSerializer::new_without_header(buf);
73        message.serialize(&mut serializer)?;
74        Ok(SerializedWill {
75            qos: self.qos,
76            retained: self.retained,
77            contents: serializer.finish(),
78        })
79    }
80
81    /// Precalculate the length of the serialized will.
82    pub(crate) fn serialized_len(&self) -> usize {
83        let prop_len = {
84            let prop_size = Properties::Slice(self.properties).size();
85            Varint(prop_size as u32).len() + prop_size
86        };
87        let topic_len = self.topic.len() + core::mem::size_of::<u16>();
88        let payload_len = self.data.len() + core::mem::size_of::<u16>();
89        topic_len + payload_len + prop_len
90    }
91
92    /// Specify the will as a retained message.
93    pub fn retained(mut self) -> Self {
94        self.retained = Retain::Retained;
95        self
96    }
97
98    /// Set the quality of service at which the will message is sent.
99    ///
100    /// # Args
101    /// * `qos` - The desired quality-of-service level to send the message at.
102    pub fn qos(mut self, qos: QoS) -> Self {
103        self.qos = qos;
104        self
105    }
106}
107
108/// A will where the topic, properties, and contents have already been serialized.
109#[derive(Debug, Copy, Clone, PartialEq)]
110pub(crate) struct SerializedWill<'a> {
111    pub(crate) qos: QoS,
112    pub(crate) retained: Retain,
113    pub(crate) contents: &'a [u8],
114}