use crate::mqtt_serde::mqttv5::common::properties::{parse_properties_hdr, Property};
use crate::mqtt_serde::parser::{parse_binary_data, parse_utf8_string, ParseError};
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct WillProperties {
pub will_delay_interval: Option<u32>,
pub payload_format_indicator: Option<u8>,
pub message_expiry_interval: Option<u32>,
pub content_type: Option<String>,
pub response_topic: Option<String>,
pub correlation_data: Option<Vec<u8>>,
pub user_properties: Vec<Property>,
}
impl WillProperties {
pub fn new() -> Self {
WillProperties::default()
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Will {
pub will_qos: u8,
pub will_retain: bool,
pub will_topic: String,
pub will_message: Vec<u8>,
pub properties: WillProperties,
}
impl Will {
pub fn new(will_topic: String, will_message: Vec<u8>, will_qos: u8, will_retain: bool) -> Self {
Will {
will_qos,
will_retain,
will_topic,
will_message,
properties: WillProperties::new(),
}
}
pub fn from_bytes(buffer: &[u8], connect_flags: u8) -> Result<(Self, usize), ParseError> {
let mut offset = 0;
let (properties, consumed) = parse_properties_hdr(buffer)?;
offset += consumed;
let (will_topic, consumed) = parse_utf8_string(&buffer[offset..])?;
offset += consumed;
let (will_message, consumed) = parse_binary_data(&buffer[offset..])?;
offset += consumed;
let will_qos = (connect_flags >> 3) & 0x03;
let will_retain = (connect_flags & 0x20) != 0;
let mut will = Will::new(will_topic, will_message, will_qos, will_retain);
for property in properties {
match property {
Property::WillDelayInterval(value) => {
will.properties.will_delay_interval = Some(value)
}
Property::PayloadFormatIndicator(value) => {
will.properties.payload_format_indicator = Some(value)
}
Property::MessageExpiryInterval(value) => {
will.properties.message_expiry_interval = Some(value);
}
Property::ContentType(value) => will.properties.content_type = Some(value),
Property::ResponseTopic(value) => will.properties.response_topic = Some(value),
Property::CorrelationData(value) => will.properties.correlation_data = Some(value),
_ => {
if let Property::UserProperty(key, value) = property {
will.properties
.user_properties
.push(Property::UserProperty(key, value));
}
}
}
}
Ok((will, offset))
}
}