riot_wrappers/coap_message/
impl_0_3.rs

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use coap_message_0_3::{
    error::RenderableOnMinimal, Code, MessageOption, MinimalWritableMessage,
    MutableWritableMessage, ReadableMessage, WithSortedOptions,
};

use crate::error::NumericError;

/// Thin wrapper around NumericError that can render and satisfies all conversion requirements
#[derive(Debug)]
#[allow(dead_code)] // reason: It's indeed just for Debug
pub struct Error(NumericError);

impl From<NumericError> for Error {
    fn from(e: NumericError) -> Error {
        Error(e)
    }
}

impl From<core::convert::Infallible> for Error {
    fn from(e: core::convert::Infallible) -> Error {
        match e {}
    }
}

impl RenderableOnMinimal for Error {
    type Error<IE: RenderableOnMinimal + core::fmt::Debug> = IE;
    fn render<M: MinimalWritableMessage>(self, msg: &mut M) -> Result<(), M::UnionError> {
        msg.set_code(Code::new(coap_numbers::code::INTERNAL_SERVER_ERROR)?);
        Ok(())
    }
}

impl<'a> MessageOption for super::MessageOption<'a> {
    fn number(&self) -> u16 {
        self.number
    }

    fn value(&self) -> &[u8] {
        self.value
    }
}

impl<'b> WithSortedOptions for super::PacketBuffer<'b> {
    // valid because gcoap just reads options from the message where they are stored in sequence
}

impl<'b> ReadableMessage for super::PacketBuffer<'b> {
    type Code = u8;
    type OptionsIter<'a>
        = super::OptionsIterator<'a, 'b>
    where
        Self: 'a;
    type MessageOption<'a>
        = super::MessageOption<'a>
    where
        Self: 'a;

    fn code(&self) -> Self::Code {
        self.get_code_raw()
    }

    fn payload(&self) -> &[u8] {
        self.payload()
    }

    fn options(&self) -> Self::OptionsIter<'_> {
        super::OptionsIterator(self.opt_iter())
    }
}

impl<'a> MinimalWritableMessage for super::ResponseMessage<'a> {
    type Code = u8;
    type OptionNumber = u16;

    type AddOptionError = Error;
    type SetPayloadError = Error;
    type UnionError = Error;

    fn set_code(&mut self, code: Self::Code) {
        self.message.set_code_raw(code);
    }

    fn add_option(&mut self, number: Self::OptionNumber, value: &[u8]) -> Result<(), Error> {
        if self.payload_written.is_some() {
            return Err(NumericError::from_constant(riot_sys::EINVAL as _).into());
        }
        self.message.opt_add_opaque(number.into(), value)?;
        Ok(())
    }

    fn set_payload(&mut self, data: &[u8]) -> Result<(), Error> {
        self.payload_mut_with_len(data.len())?.copy_from_slice(data);
        Ok(())
    }

    #[inline]
    #[allow(refining_impl_trait_reachable)]
    fn promote_to_mutable_writable_message(&mut self) -> Option<&mut Self> {
        Some(self)
    }
}

impl<'a> MutableWritableMessage for super::ResponseMessage<'a> {
    fn available_space(&self) -> usize {
        self.message.payload().len()
    }

    fn payload_mut_with_len(&mut self, len: usize) -> Result<&mut [u8], Error> {
        self.payload_written = Some(len);
        let payload = self.message.payload_mut();
        if let Some((pm, pl)) = payload.get_mut(..len + 1).and_then(<[u8]>::split_first_mut) {
            *pm = 0xff;
            Ok(pl)
        } else {
            Err(NumericError::from_constant(riot_sys::EINVAL as _).into())
        }
    }

    fn truncate(&mut self, len: usize) -> Result<(), Error> {
        if self.payload_written.is_none() {
            // payload() will not even return anything sensible yet
            return Err(NumericError::from_constant(riot_sys::EINVAL as _).into());
        }
        let pl_len = self.message.payload().len() - 1;
        if len > pl_len {
            return Err(NumericError::from_constant(riot_sys::EINVAL as _).into());
        }
        self.payload_written = Some(len);
        Ok(())
    }

    fn mutate_options<F>(&mut self, mut callback: F)
    where
        F: FnMut(Self::OptionNumber, &mut [u8]),
    {
        for (opt_num, slice) in self.message.opt_iter_mut() {
            callback(opt_num.into(), slice);
        }
    }
}