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))
    }
}