mqtt_async_embedded/
util.rs1use crate::error::{MqttError, ProtocolError};
7use crate::packet;
8use crate::transport;
9use heapless::Vec;
10
11pub fn read_variable_byte_integer(
15 cursor: &mut usize,
16 buf: &[u8],
17) -> Result<usize, MqttError<transport::ErrorPlaceHolder>> {
18 let mut multiplier = 1;
19 let mut value = 0;
20 let mut i = 0;
21 loop {
22 let encoded_byte = buf
23 .get(*cursor + i)
24 .ok_or(MqttError::Protocol(ProtocolError::MalformedPacket))?;
25 value += (encoded_byte & 127) as usize * multiplier;
26 if (encoded_byte & 128) == 0 {
27 break;
28 }
29 multiplier *= 128;
30 i += 1;
31 if i >= 4 {
32 return Err(MqttError::Protocol(ProtocolError::MalformedPacket));
33 }
34 }
35 *cursor += i + 1;
36 Ok(value)
37}
38
39pub fn write_variable_byte_integer(
41 cursor: &mut usize,
42 buf: &mut [u8],
43 mut val: usize,
44) -> Result<(), MqttError<transport::ErrorPlaceHolder>> {
45 loop {
46 let mut encoded_byte = (val % 128) as u8;
47 val /= 128;
48 if val > 0 {
49 encoded_byte |= 128;
50 }
51 *buf.get_mut(*cursor)
53 .ok_or(MqttError::BufferTooSmall)? = encoded_byte;
54 *cursor += 1;
55 if val == 0 {
56 break;
57 }
58 }
59 Ok(())
60}
61
62pub fn write_variable_byte_integer_len(
64 buf: &mut [u8],
65 mut val: usize,
66) -> Result<usize, MqttError<transport::ErrorPlaceHolder>> {
67 let mut i = 0;
68 loop {
69 let mut encoded_byte = (val % 128) as u8;
70 val /= 128;
71 if val > 0 {
72 encoded_byte |= 128;
73 }
74 *buf.get_mut(i).ok_or(MqttError::BufferTooSmall)? = encoded_byte;
76 i += 1;
77 if val == 0 {
78 break;
79 }
80 }
81 Ok(i)
82}
83
84pub fn read_utf8_string<'a>(
86 cursor: &mut usize,
87 buf: &'a [u8],
88) -> Result<&'a str, MqttError<transport::ErrorPlaceHolder>> {
89 let len = u16::from_be_bytes(
90 buf.get(*cursor..*cursor + 2)
91 .ok_or(MqttError::Protocol(ProtocolError::MalformedPacket))?
92 .try_into()
93 .unwrap(),
94 ) as usize;
95 *cursor += 2;
96 let s = core::str::from_utf8(
97 buf.get(*cursor..*cursor + len)
98 .ok_or(MqttError::Protocol(ProtocolError::MalformedPacket))?,
99 )
100 .map_err(|_| MqttError::Protocol(ProtocolError::InvalidUtf8String))?;
101 *cursor += len;
102 Ok(s)
103}
104
105pub fn write_utf8_string(
107 buf: &mut [u8],
108 s: &str,
109) -> Result<usize, MqttError<transport::ErrorPlaceHolder>> {
110 let len = s.len();
111 if len > u16::MAX as usize {
112 return Err(MqttError::Protocol(ProtocolError::PayloadTooLarge));
113 }
114 let len_bytes = (len as u16).to_be_bytes();
115
116 let required_space = 2 + len;
117 let slice = buf
118 .get_mut(0..required_space)
119 .ok_or(MqttError::BufferTooSmall)?;
120
121 slice[0..2].copy_from_slice(&len_bytes);
122 slice[2..].copy_from_slice(s.as_bytes());
123 Ok(required_space)
124}
125
126#[cfg(feature = "v5")]
128pub fn read_properties<'a>(
129 cursor: &mut usize,
130 buf: &'a [u8],
131) -> Result<Vec<packet::Property<'a>, 8>, MqttError<transport::ErrorPlaceHolder>> {
132 let mut properties = Vec::new();
133 let prop_len = read_variable_byte_integer(cursor, buf)?;
134 let prop_end = *cursor + prop_len;
135
136 while *cursor < prop_end {
137 let id = buf[*cursor];
138 *cursor += 1;
139 let data_start = *cursor;
140 let data_len = 1; *cursor += data_len;
144 properties
145 .push(packet::Property {
146 id,
147 data: &buf[data_start..data_start + data_len],
148 })
149 .map_err(|_| MqttError::Protocol(ProtocolError::TooManyProperties))?;
150 }
151 Ok(properties)
152}
153
154#[cfg(feature = "v5")]
156pub fn write_properties(
157 cursor: &mut usize,
158 buf: &mut [u8],
159 properties: &[packet::Property],
160) -> Result<(), MqttError<transport::ErrorPlaceHolder>> {
161 let prop_len_cursor_start = *cursor;
163 *cursor += 1; let props_start = *cursor;
166 for prop in properties {
167 buf[*cursor] = prop.id;
168 *cursor += 1;
169 buf[*cursor..*cursor + prop.data.len()].copy_from_slice(prop.data);
170 *cursor += prop.data.len();
171 }
172 let total_prop_len = *cursor - props_start;
173
174 let mut temp_cursor = prop_len_cursor_start;
176 let _ = crate::util::write_variable_byte_integer(&mut temp_cursor, buf, total_prop_len)?;
177
178 Ok(())
179}
180