async_coap/message/
std_encoder.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use super::codec::*;
17use super::*;
18
19/// A class for writing stand-alone messages to a mutable byte slice.
20#[derive(Debug)]
21pub struct BufferMessageEncoder<'buf> {
22    buffer: &'buf mut [u8],
23    len: usize,
24    option_start: usize,
25    payload_start: usize,
26    last_option: OptionNumber,
27}
28
29impl<'buf> BufferMessageEncoder<'buf> {
30    /// The minimum size buffer that can be passed into `new`.
31    pub const MIN_MESSAGE_BUFFER_LEN: usize = 12;
32
33    /// Creates a new `BufferMessageEncoder` using the given buffer.
34    pub fn new(buffer: &'buf mut [u8]) -> BufferMessageEncoder<'buf> {
35        if buffer.len() < BufferMessageEncoder::MIN_MESSAGE_BUFFER_LEN {
36            panic!("Buffer too small");
37        }
38
39        // Set version on first byte.
40        buffer[0] = 0b01000000;
41
42        BufferMessageEncoder {
43            buffer,
44            len: 4,
45            option_start: 4,
46            payload_start: 4,
47            last_option: Default::default(),
48        }
49    }
50
51    /// Returns a byte slice containing the encoded message.
52    pub fn as_bytes(&self) -> &[u8] {
53        &self.buffer[..self.len]
54    }
55
56    /// Returns the token set for this message.
57    pub fn msg_token(&self) -> MsgToken {
58        let token_len = (self.buffer[0] & COAP_MSG_TKL_MASK) as usize;
59        MsgToken::new(&self.buffer[4..4 + token_len])
60    }
61}
62
63impl<'buf> std::fmt::Display for BufferMessageEncoder<'buf> {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        CoapByteDisplayFormatter(self.as_bytes()).fmt(f)
66    }
67}
68
69impl<'buf> core::ops::Deref for BufferMessageEncoder<'buf> {
70    type Target = [u8];
71
72    fn deref(&self) -> &Self::Target {
73        self.as_bytes()
74    }
75}
76
77impl<'buf> MessageWrite for BufferMessageEncoder<'buf> {
78    fn set_msg_type(&mut self, tt: MsgType) {
79        self.buffer[0] = (self.buffer[0] & !COAP_MSG_T_MASK) | ((tt as u8) << COAP_MSG_T_OFFS);
80    }
81
82    fn set_msg_id(&mut self, msg_id: u16) {
83        self.buffer[2] = (msg_id >> 8) as u8;
84        self.buffer[3] = (msg_id >> 0) as u8;
85    }
86
87    fn set_msg_code(&mut self, code: MsgCode) {
88        self.buffer[1] = code as u8;
89    }
90
91    fn set_msg_token(&mut self, token: MsgToken) {
92        if self.option_start != 4 + token.len() {
93            self.len = 4 + token.len();
94            self.option_start = self.len;
95            self.payload_start = self.option_start;
96
97            self.buffer[0] = (self.buffer[0] & !COAP_MSG_TKL_MASK) | token.len() as u8;
98        }
99
100        self.buffer[4..4 + token.len()].copy_from_slice(token.as_bytes());
101    }
102
103    fn append_payload_bytes(&mut self, body: &[u8]) -> Result<(), Error> {
104        if self.len == self.payload_start {
105            if self.payload_start >= self.buffer.len() {
106                return Err(Error::OutOfSpace);
107            }
108            // Append an end-of-options marker.
109            self.buffer[self.payload_start] = 0xFF;
110            self.len += 1;
111        }
112
113        let new_body_end = self.len + body.len();
114
115        if new_body_end > self.buffer.len() {
116            return Err(Error::OutOfSpace);
117        }
118
119        self.buffer[self.len..new_body_end].copy_from_slice(body);
120        self.len = new_body_end;
121
122        Ok(())
123    }
124
125    fn clear(&mut self) {
126        self.buffer[0] = 0b01000000;
127        self.len = 4;
128        self.option_start = 4;
129        self.payload_start = 4;
130        self.last_option = Default::default();
131    }
132}
133
134impl<'buf> OptionInsert for BufferMessageEncoder<'buf> {
135    fn insert_option_with_bytes(&mut self, key: OptionNumber, value: &[u8]) -> Result<(), Error> {
136        if self.last_option == key && !key.is_repeatable() {
137            panic!("Option {} is not repeatable", key);
138            //return Err(Error::OptionNotRepeatable);
139        }
140        let option_start = self.option_start;
141        let (mut len, last_option) = insert_option(
142            &mut self.buffer[option_start..],
143            self.len - option_start,
144            self.last_option,
145            key,
146            value,
147        )?;
148
149        len += option_start;
150        self.last_option = last_option;
151        self.len = len;
152        self.payload_start = len;
153
154        Ok(())
155    }
156}
157
158/// A class for writing stand-alone messages to a heap-allocated [`Vec`].
159#[derive(Debug)]
160pub struct VecMessageEncoder {
161    buffer: Vec<u8>,
162    option_start: usize,
163    payload_start: usize,
164    last_option: OptionNumber,
165}
166
167impl VecMessageEncoder {
168    /// Creates a new `VecMessageEncoder` instance.
169    pub fn new() -> VecMessageEncoder {
170        Self::with_payload_capacity(16)
171    }
172
173    /// Creates a new `VecMessageEncoder` instance with a specific capacity.
174    pub fn with_payload_capacity(capacity: usize) -> VecMessageEncoder {
175        let mut buffer = Vec::with_capacity(16 + capacity);
176
177        // Set version on first byte.
178        buffer.push(0b01000000);
179        buffer.resize(4, 0);
180
181        VecMessageEncoder {
182            buffer,
183            option_start: 4,
184            payload_start: 4,
185            last_option: Default::default(),
186        }
187    }
188
189    /// Returns a byte slice containing the encoded message.
190    pub fn as_bytes(&self) -> &[u8] {
191        &self.buffer
192    }
193
194    /// Returns the token set for this message.
195    pub fn msg_token(&self) -> MsgToken {
196        let token_len = (self.buffer[0] & COAP_MSG_TKL_MASK) as usize;
197        MsgToken::new(&self.buffer[4..4 + token_len])
198    }
199}
200
201impl std::convert::From<VecMessageEncoder> for Vec<u8> {
202    fn from(x: VecMessageEncoder) -> Self {
203        x.buffer
204    }
205}
206
207impl std::convert::From<VecMessageEncoder> for OwnedImmutableMessage {
208    fn from(x: VecMessageEncoder) -> Self {
209        OwnedImmutableMessage::new(x.buffer).expect("Encoding corrupt")
210    }
211}
212
213impl Default for VecMessageEncoder {
214    fn default() -> Self {
215        Self::new()
216    }
217}
218
219impl std::fmt::Display for VecMessageEncoder {
220    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221        CoapByteDisplayFormatter(self.as_bytes()).fmt(f)
222    }
223}
224
225impl core::ops::Deref for VecMessageEncoder {
226    type Target = [u8];
227
228    fn deref(&self) -> &Self::Target {
229        self.as_bytes()
230    }
231}
232
233impl MessageWrite for VecMessageEncoder {
234    fn set_msg_type(&mut self, tt: MsgType) {
235        self.buffer[0] = (self.buffer[0] & !COAP_MSG_T_MASK) | ((tt as u8) << COAP_MSG_T_OFFS);
236    }
237
238    fn set_msg_id(&mut self, msg_id: u16) {
239        self.buffer[2] = (msg_id >> 8) as u8;
240        self.buffer[3] = (msg_id >> 0) as u8;
241    }
242
243    fn set_msg_code(&mut self, code: MsgCode) {
244        self.buffer[1] = code as u8;
245    }
246
247    fn set_msg_token(&mut self, token: MsgToken) {
248        if self.option_start != 4 + token.len() {
249            self.buffer.resize(4 + token.len(), 0);
250            self.option_start = self.buffer.len();
251            self.payload_start = self.option_start;
252
253            self.buffer[0] = (self.buffer[0] & !COAP_MSG_TKL_MASK) | token.len() as u8;
254        }
255        self.buffer[4..4 + token.len()].copy_from_slice(token.as_bytes());
256    }
257
258    fn append_payload_bytes(&mut self, body: &[u8]) -> Result<(), Error> {
259        if self.buffer.len() == self.payload_start {
260            // Append an end-of-options marker.
261            self.buffer.push(0xFF);
262        }
263        self.buffer.extend_from_slice(body);
264        Ok(())
265    }
266
267    fn clear(&mut self) {
268        self.buffer[0] = 0b01000000;
269        self.buffer.resize(4, 0);
270        self.option_start = 4;
271        self.payload_start = 4;
272        self.last_option = Default::default();
273    }
274}
275
276impl OptionInsert for VecMessageEncoder {
277    fn insert_option_with_bytes(&mut self, key: OptionNumber, value: &[u8]) -> Result<(), Error> {
278        if self.last_option == key && !key.is_repeatable() {
279            return Err(Error::OptionNotRepeatable);
280        }
281
282        let option_start = self.option_start;
283
284        let workspace = value.len() + 5;
285
286        let len = self.buffer.len();
287        self.buffer.resize(self.buffer.len() + workspace, 0);
288
289        let (mut len, last_option) = insert_option(
290            &mut self.buffer[option_start..],
291            len - option_start,
292            self.last_option,
293            key,
294            value,
295        )?;
296
297        len += option_start;
298        self.buffer.truncate(len);
299        self.last_option = last_option;
300        self.payload_start = len;
301
302        Ok(())
303    }
304}
305
306#[cfg(test)]
307mod tests {
308    use super::*;
309    use crate::option::*;
310
311    #[test]
312    fn message_builder_rfc7252_fig_16() {
313        let buffer = &mut [0u8; 200];
314
315        let mut builder = BufferMessageEncoder::new(buffer);
316        builder.set_msg_type(MsgType::Con);
317        builder.set_msg_code(MsgCode::MethodGet);
318        builder.set_msg_id(0x7d34);
319        assert_eq!(Ok(()), builder.insert_option(URI_PATH, "temperature"));
320        let packet_calc: &[u8] = &builder;
321        let packet_real = &[
322            0b01000000, 1, 0x7d, 0x34, 0xbb, b't', b'e', b'm', b'p', b'e', b'r', b'a', b't', b'u',
323            b'r', b'e',
324        ];
325        println!("request: {:#x?}", packet_calc);
326        assert_eq!(packet_real, packet_calc);
327
328        let parser = StandardMessageParser::new(packet_real).unwrap();
329        assert_eq!(MsgType::Con, parser.msg_type());
330        assert_eq!(MsgCode::MethodGet, parser.msg_code());
331        assert_eq!(0x7d34, parser.msg_id());
332        assert_eq!(MsgToken::EMPTY, parser.msg_token());
333        assert_eq!(None, parser.content_format());
334        assert_eq!(None, parser.accept());
335        assert!(parser.payload().is_empty());
336        let mut iter = parser.options();
337        assert_eq!(
338            Some(Ok((OptionNumber::URI_PATH, &b"temperature"[..]))),
339            iter.next()
340        );
341        assert_eq!(None, iter.next());
342
343        let mut builder = BufferMessageEncoder::new(buffer);
344        builder.set_msg_type(MsgType::Ack);
345        builder.set_msg_code(MsgCode::SuccessContent);
346        builder.set_msg_id(0x7d34);
347        assert_eq!(Ok(()), builder.append_payload_string(r#"22.3 C"#));
348        let packet_calc: &[u8] = &builder;
349        let packet_real = &[
350            0b01100000, 69, 0x7d, 0x34, 0xff, b'2', b'2', b'.', b'3', b' ', b'C',
351        ];
352        println!("response: {:#x?}", packet_calc);
353        assert_eq!(packet_real, packet_calc);
354    }
355
356    #[test]
357    fn message_builder_rfc7252_fig_17() {
358        let buffer = &mut [0u8; 200];
359
360        let mut builder = BufferMessageEncoder::new(buffer);
361        builder.set_msg_type(MsgType::Con);
362        builder.set_msg_code(MsgCode::MethodGet);
363        builder.set_msg_id(0x7d34);
364        builder.set_msg_token(MsgToken::from(0x20));
365        assert_eq!(Ok(()), builder.insert_option(URI_PATH, "temperature"));
366        let packet_calc: &[u8] = &builder;
367        let packet_real = &[
368            0b01000001, 1, 0x7d, 0x34, 0x20, 0xbb, b't', b'e', b'm', b'p', b'e', b'r', b'a', b't',
369            b'u', b'r', b'e',
370        ];
371        println!("request: {:#x?}", packet_calc);
372        assert_eq!(packet_real, packet_calc);
373
374        let mut builder = BufferMessageEncoder::new(buffer);
375        builder.set_msg_type(MsgType::Ack);
376        builder.set_msg_code(MsgCode::SuccessContent);
377        builder.set_msg_id(0x7d34);
378        builder.set_msg_token(MsgToken::from(0x20));
379        assert_eq!(Ok(()), builder.append_payload_string(r#"22.3 C"#));
380        let packet_calc: &[u8] = &builder;
381        let packet_real = &[
382            0b01100001, 69, 0x7d, 0x34, 0x20, 0xff, b'2', b'2', b'.', b'3', b' ', b'C',
383        ];
384        println!("response: {:#x?}", packet_calc);
385        assert_eq!(packet_real, packet_calc);
386    }
387
388    #[test]
389    fn message_builder_append_body() {
390        let buffer = &mut [0u8; 200];
391
392        let mut builder = BufferMessageEncoder::new(buffer);
393        builder.set_msg_type(MsgType::Ack);
394        builder.set_msg_code(MsgCode::SuccessContent);
395        builder.set_msg_id(0x7d34);
396        builder.set_msg_token(MsgToken::from(0x20));
397        assert_eq!(Ok(()), builder.append_payload_string(r#"22."#));
398        assert_eq!(Ok(()), builder.append_payload_string(r#"3 C"#));
399        let packet_calc: &[u8] = &builder;
400        let packet_real = &[
401            0b01100001, 69, 0x7d, 0x34, 0x20, 0xff, b'2', b'2', b'.', b'3', b' ', b'C',
402        ];
403        println!("response: {:#x?}", packet_calc);
404        assert_eq!(packet_real, packet_calc);
405    }
406
407    #[test]
408    fn message_builder_misc() {
409        let buffer = &mut [0u8; 200];
410        let mut builder = BufferMessageEncoder::new(buffer);
411        builder.set_msg_type(MsgType::Con);
412        builder.set_msg_code(MsgCode::MethodPost);
413        builder.set_msg_id(0x7d34);
414        builder.set_msg_token(MsgToken::from(0x2021));
415        assert_eq!(
416            Ok(()),
417            builder.insert_option(CONTENT_FORMAT, ContentFormat::TEXT_PLAIN_UTF8)
418        );
419        assert_eq!(Ok(()), builder.insert_option(URI_PATH, "temp"));
420        assert_eq!(Ok(()), builder.append_payload_string(r#"22."#));
421        assert_eq!(Ok(()), builder.append_payload_string(r#"3 C"#));
422        let packet_calc: &[u8] = &builder;
423        let packet_real = &[
424            0b01000010, 2, 0x7d, 0x34, 0x20, 0x21, 0xb4, b't', b'e', b'm', b'p', 0x10, 0xff, b'2',
425            b'2', b'.', b'3', b' ', b'C',
426        ];
427        println!("response: {:#x?}", packet_calc);
428        assert_eq!(packet_real, packet_calc);
429
430        let parser = StandardMessageParser::new(packet_real).unwrap();
431
432        assert_eq!(MsgType::Con, parser.msg_type());
433        assert_eq!(MsgCode::MethodPost, parser.msg_code());
434        assert_eq!(0x7d34, parser.msg_id());
435        assert_eq!(MsgToken::from(0x2021), parser.msg_token());
436
437        assert_eq!(
438            Some(ContentFormat::TEXT_PLAIN_UTF8),
439            parser.content_format()
440        );
441        assert_eq!(None, parser.accept());
442        assert_eq!(b"22.3 C", parser.payload());
443
444        let mut iter = parser.options();
445        assert_eq!(
446            Some(Ok((OptionNumber::URI_PATH, &b"temp"[..]))),
447            iter.next()
448        );
449        assert_eq!(
450            Some(Ok((OptionNumber::CONTENT_FORMAT, &b""[..]))),
451            iter.next()
452        );
453        assert_eq!(None, iter.next());
454
455        let mut iter = parser.options();
456        assert_eq!(Some(Ok("temp")), iter.find_next_of(URI_PATH));
457        assert_eq!(None, iter.find_next_of(URI_PATH));
458        assert_eq!(
459            Some(Ok(ContentFormat::TEXT_PLAIN_UTF8)),
460            iter.find_next_of(CONTENT_FORMAT)
461        );
462        assert_eq!(None, iter.next());
463    }
464
465    #[test]
466    fn vec_message_builder_misc() {
467        let mut builder = VecMessageEncoder::new();
468        builder.set_msg_type(MsgType::Con);
469        builder.set_msg_code(MsgCode::MethodPost);
470        builder.set_msg_id(0x7d34);
471        builder.set_msg_token(MsgToken::from(0x2021));
472        assert_eq!(
473            Ok(()),
474            builder.insert_option(CONTENT_FORMAT, ContentFormat::TEXT_PLAIN_UTF8)
475        );
476        assert_eq!(Ok(()), builder.insert_option(URI_PATH, "temp"));
477        assert_eq!(Ok(()), builder.append_payload_string(r#"22."#));
478        assert_eq!(Ok(()), builder.append_payload_string(r#"3 C"#));
479        let packet_calc: &[u8] = &builder;
480        let packet_real = &[
481            0b01000010, 2, 0x7d, 0x34, 0x20, 0x21, 0xb4, b't', b'e', b'm', b'p', 0x10, 0xff, b'2',
482            b'2', b'.', b'3', b' ', b'C',
483        ];
484        println!("response: {:#x?}", packet_calc);
485        assert_eq!(packet_real, packet_calc);
486
487        let parser = StandardMessageParser::new(packet_real).unwrap();
488
489        assert_eq!(MsgType::Con, parser.msg_type());
490        assert_eq!(MsgCode::MethodPost, parser.msg_code());
491        assert_eq!(0x7d34, parser.msg_id());
492        assert_eq!(MsgToken::from(0x2021), parser.msg_token());
493
494        assert_eq!(
495            Some(ContentFormat::TEXT_PLAIN_UTF8),
496            parser.content_format()
497        );
498        assert_eq!(None, parser.accept());
499        assert_eq!(b"22.3 C", parser.payload());
500
501        let mut iter = parser.options();
502        assert_eq!(
503            Some(Ok((OptionNumber::URI_PATH, &b"temp"[..]))),
504            iter.next()
505        );
506        assert_eq!(
507            Some(Ok((OptionNumber::CONTENT_FORMAT, &b""[..]))),
508            iter.next()
509        );
510        assert_eq!(None, iter.next());
511
512        let mut iter = parser.options();
513        assert_eq!(Some(Ok("temp")), iter.find_next_of(URI_PATH));
514        assert_eq!(None, iter.find_next_of(URI_PATH));
515        assert_eq!(
516            Some(Ok(ContentFormat::TEXT_PLAIN_UTF8)),
517            iter.find_next_of(CONTENT_FORMAT)
518        );
519        assert_eq!(None, iter.next());
520    }
521
522    #[test]
523    fn message_builder_reset() {
524        let buffer = &mut [0u8; 200];
525        let mut builder = BufferMessageEncoder::new(buffer);
526        builder.set_msg_type(MsgType::Con);
527        builder.set_msg_code(MsgCode::Empty);
528        builder.set_msg_id(0x0000);
529        builder.set_msg_token(MsgToken::EMPTY);
530        let packet_calc: &[u8] = &builder;
531        let packet_real = &[0b01000000, 0, 0x00, 0x00];
532        println!("response: {:#x?}", packet_calc);
533        assert_eq!(packet_real, packet_calc);
534
535        let parser = StandardMessageParser::new(packet_real).unwrap();
536
537        assert_eq!(MsgType::Con, parser.msg_type());
538        assert_eq!(MsgCode::Empty, parser.msg_code());
539        assert_eq!(0x0, parser.msg_id());
540        assert_eq!(MsgToken::EMPTY, parser.msg_token());
541
542        assert_eq!(None, parser.content_format());
543        assert_eq!(None, parser.accept());
544        assert_eq!(b"", parser.payload());
545    }
546}