1use crate::build_enum;
2use crate::DataType;
3use crate::Error;
4use std::collections::BTreeMap;
5use std::convert::TryFrom;
6use std::io;
7
8build_enum!(Identifier {
9 PayloadFormatIndicator = 0x01,
10 MessageExpiryInterval = 0x02,
11 ContentType = 0x03,
12 ResponseTopic = 0x08,
13 CorrelationData = 0x09,
14 SubscriptionIdentifier = 0x0b,
15 SessionExpiryInterval = 0x11,
16 AssignedClientIdentifier = 0x12,
17 ServerKeepAlive = 0x13,
18 AuthenticationMethod = 0x15,
19 AuthenticationData = 0x16,
20 RequestProblemInformation = 0x17,
21 WillDelayInterval = 0x18,
22 RequestResponseInformation = 0x19,
23 ResponseInformation = 0x1a,
24 ServerReference = 0x1c,
25 ReasonString = 0x1f,
26 ReceiveMaximum = 0x21,
27 TopicAliasMaximum = 0x22,
28 TopicAlias = 0x23,
29 MaximumQos = 0x24,
30 RetainAvailable = 0x25,
31 UserProperty = 0x26,
32 MaximumPacketSize = 0x27,
33 WildcardSubscriptionAvailable = 0x28,
34 SubscriptionIdentifierAvailable = 0x29,
35 SharedSubscriptionAvailable = 0x2a
36});
37
38pub struct Property {
51 pub values: BTreeMap<Identifier, DataType>,
52}
53
54impl Property {
55 pub fn new<R: io::Read>(reader: &mut R) -> Result<Self, Error> {
57 let length = DataType::parse_two_byte_int(reader)?;
58 let mut properties = BTreeMap::new();
59
60 for _i in 0..length.into() {
61 let identifier = Self::parse_identifier(reader)?;
62 let data_type = Self::parse_type(&identifier, reader)?;
63 properties.insert(identifier, data_type);
64 }
65
66 return Ok(Self { values: properties });
67 }
68
69 fn parse_identifier<R: io::Read>(reader: &mut R) -> Result<Identifier, Error> {
71 let mut id_buffer = [0; 1];
72 reader.read(&mut id_buffer)?;
73 return Ok(Identifier::try_from(id_buffer[0])?);
74 }
75
76 fn parse_type<R: io::Read>(identifier: &Identifier, reader: &mut R) -> Result<DataType, Error> {
78 use Identifier::*;
79
80 return match identifier {
81 PayloadFormatIndicator
82 | RequestProblemInformation
83 | RequestResponseInformation
84 | MaximumQos
85 | RetainAvailable
86 | WildcardSubscriptionAvailable
87 | SubscriptionIdentifierAvailable
88 | SharedSubscriptionAvailable => DataType::parse_byte(reader),
89 ServerKeepAlive | ReceiveMaximum | TopicAliasMaximum | TopicAlias => {
90 DataType::parse_two_byte_int(reader)
91 }
92 MessageExpiryInterval | SessionExpiryInterval | WillDelayInterval | MaximumPacketSize => {
93 DataType::parse_four_byte_int(reader)
94 }
95 SubscriptionIdentifier => DataType::parse_variable_byte_int(reader),
96 UserProperty => DataType::parse_utf8_string_pair(reader),
97 CorrelationData | AuthenticationData => DataType::parse_binary_data(reader),
98 ContentType
99 | ResponseTopic
100 | AssignedClientIdentifier
101 | AuthenticationMethod
102 | ResponseInformation
103 | ServerReference
104 | ReasonString => DataType::parse_utf8_string(reader),
105 };
106 }
107
108 pub fn generate(&self) -> Result<Vec<u8>, Error> {
110 let length = u16::try_from(self.values.len() & 0xFFFF)
112 .unwrap()
113 .to_be_bytes()
114 .to_vec();
115
116 let mut bytes = vec![];
118 bytes.push(length);
119
120 for (key, value) in self.values.iter() {
122 let id: u8 = u8::from(*key);
123 bytes.push(vec![id]);
124 bytes.push(value.into_bytes()?);
125 }
126
127 return Ok(bytes.concat());
128 }
129}