1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
//! Implementation of [coap_message::ReadableMessage] based on a serialized message
//!
//! [Message] is the main struct of this module.
use coap_message::*;
use crate::option_iteration::*;
/// An iterator producing [MessageOption]s by running along an encoded CoAP message options stream
/// by using a [OptPayloadReader] and discarding the payload.
// FIXME make argument non-pub once coapwsmessage figures out a better way to use Message
pub struct OptionsIter<'a>(pub OptPayloadReader<'a>);
impl<'a> Iterator for OptionsIter<'a> {
type Item = MessageOption<'a>;
fn next(&mut self) -> Option<MessageOption<'a>> {
match self.0.next() {
Some(OptItem::Option { number, data }) => Some(MessageOption {
number,
value: data,
}),
Some(OptItem::Error { .. }) => panic!("coap-message has no error handling"),
// No need to recurse or loop -- it's always the last one
Some(OptItem::Payload(_)) => None,
None => None,
}
}
}
/// A simple [coap_message::MessageOption] implementation for memory-mapped CoAP messages
pub struct MessageOption<'a> {
number: u16,
value: &'a [u8],
}
impl<'a> coap_message::MessageOption for MessageOption<'a> {
fn number(&self) -> u16 {
self.number
}
fn value(&self) -> &[u8] {
self.value
}
}
/// A CoAP message that resides in contiguous readable memory
///
/// This implementation does not attempt to do any early validation. On encoding errors discovered
/// at runtime, it simply emits the critical-and-not-safe-to-forward CoAP option 65535, which to
/// the indication indicates that something went wrong FIXME but so far it panics.
#[derive(Copy, Clone)]
pub struct Message<'a> {
code: u8,
options_and_payload: &'a [u8],
}
impl<'a> Message<'a> {
pub fn new(code: u8, options_and_payload: &'a [u8]) -> Self {
Self {
code,
options_and_payload,
}
}
}
impl<'m> ReadableMessage for Message<'m> {
type Code = u8;
// We *can* make them live longer -- should we? Probably doesn't change anything, but at least
// it's teasing the compiler a bit.
type MessageOption<'a> = MessageOption<'m>;
type OptionsIter<'a>
where
Self: 'a,
= OptionsIter<'m>;
fn code(&self) -> u8 {
self.code
}
// This is one of the not-most-efficient things mentioned in the module introduction: It's
// iterating through the complete options stream on every payload call, rather than memoizing
// its location when the options are iterated over.
fn payload(&self) -> &[u8] {
let empty: &[u8] = &[];
// ... into which we'll index
let optpayload = self.options_and_payload;
OptPayloadReader::new(optpayload)
.filter(|x| !matches!(x, OptItem::Option { .. }))
.next()
.map(|x| {
if let OptItem::Payload(data) = x {
// Can't return data itself because the iterator doesn't outlive this function
// To be replaced when ptr_wrapping_offset_from is stabilized
let offset = data.as_ptr() as usize - optpayload.as_ptr() as usize;
&optpayload[offset..]
} else {
panic!("Error before payload")
}
})
.unwrap_or(&empty)
}
fn options(&self) -> OptionsIter<'m> {
OptionsIter(OptPayloadReader::new(self.options_and_payload))
}
}