async_coap/message/
read.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::*;
17use crate::option::OptionIterator;
18
19/// Trait for reading the various parts of a CoAP message.
20pub trait MessageRead {
21    /// Gets the message code for this message.
22    fn msg_code(&self) -> MsgCode;
23
24    /// Gets the message type for this message.
25    fn msg_type(&self) -> MsgType;
26
27    /// Gets the message id for this message.
28    fn msg_id(&self) -> MsgId;
29
30    /// Gets the message token for this message.
31    fn msg_token(&self) -> MsgToken;
32
33    /// Gets the payload as a byte slice.
34    fn payload(&self) -> &[u8];
35
36    /// Gets an iterator for processing the options of the message.
37    fn options(&self) -> OptionIterator<'_>;
38
39    /// Writes this message to the given `target` that implements [`MessageWrite`].
40    ///
41    /// If this message has a message id ([`msg_id`][MessageRead::msg_id]) of zero, the message
42    /// id will not be written to `target`.
43    fn write_msg_to(&self, target: &mut dyn MessageWrite) -> Result<(), Error> {
44        target.set_msg_type(self.msg_type());
45        target.set_msg_code(self.msg_code());
46        let msg_id = self.msg_id();
47        if msg_id != 0 {
48            target.set_msg_id(self.msg_id());
49        }
50        target.set_msg_token(self.msg_token());
51
52        for opt in self.options() {
53            let opt = opt?;
54            target.insert_option_with_bytes(opt.0, opt.1)?;
55        }
56
57        target.append_payload_bytes(self.payload())?;
58        Ok(())
59    }
60
61    /// Gets the payload as a string slice.
62    fn payload_as_str(&self) -> Option<&str> {
63        std::str::from_utf8(self.payload()).ok()
64    }
65
66    /// Indicates the content format of the payload, if specified.
67    fn content_format(&self) -> Option<ContentFormat>;
68
69    /// Indicates the content format that the sender of the message will accept
70    /// for the payload of the response, if specified.
71    fn accept(&self) -> Option<ContentFormat>;
72
73    /// Returns the value of the `block2` option for this message, if any.
74    fn block2(&self) -> Option<BlockInfo>;
75
76    /// Returns the value of the `block1` option for this message, if any.
77    fn block1(&self) -> Option<BlockInfo>;
78}
79
80impl<'a> ToOwned for dyn MessageRead + 'a {
81    type Owned = OwnedImmutableMessage;
82
83    fn to_owned(&self) -> Self::Owned {
84        let mut target = VecMessageEncoder::default();
85
86        // UNWRAP-SAFETY: Should only happen under severe memory pressure.
87        self.write_msg_to(&mut target).unwrap();
88
89        target.into()
90    }
91}
92
93/// A type representing a reset message.
94///
95/// This type is useful for quickly writing out reset responses via the
96/// [`write_msg_to`] method.
97///
98/// [`write_msg_to`]: MessageRead::write_msg_to
99#[derive(Debug, Copy, Clone, Eq, PartialEq)]
100pub struct ResetMessage;
101impl std::fmt::Display for ResetMessage {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        MessageDisplay(self).fmt(f)
104    }
105}
106impl MessageRead for ResetMessage {
107    fn msg_code(&self) -> MsgCode {
108        MsgCode::Empty
109    }
110
111    fn msg_type(&self) -> MsgType {
112        MsgType::Res
113    }
114
115    fn msg_id(&self) -> u16 {
116        0
117    }
118
119    fn msg_token(&self) -> MsgToken {
120        Default::default()
121    }
122
123    fn payload(&self) -> &[u8] {
124        Default::default()
125    }
126
127    fn content_format(&self) -> Option<ContentFormat> {
128        None
129    }
130
131    fn accept(&self) -> Option<ContentFormat> {
132        None
133    }
134
135    fn block2(&self) -> Option<BlockInfo> {
136        None
137    }
138
139    fn block1(&self) -> Option<BlockInfo> {
140        None
141    }
142
143    fn options(&self) -> OptionIterator<'_> {
144        Default::default()
145    }
146
147    fn write_msg_to(&self, target: &mut dyn MessageWrite) -> Result<(), Error> {
148        target.set_msg_code(MsgCode::Empty);
149        target.set_msg_type(MsgType::Res);
150        target.set_msg_token(MsgToken::EMPTY);
151        Ok(())
152    }
153}
154
155/// A type representing an acknowledgement message.
156///
157/// This type is useful for quickly writing out reset responses via the
158/// [`write_msg_to`] method.
159///
160/// [`write_msg_to`]: MessageRead::write_msg_to
161#[derive(Debug, Copy, Clone, Eq, PartialEq)]
162pub struct AckMessage;
163impl std::fmt::Display for AckMessage {
164    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165        MessageDisplay(self).fmt(f)
166    }
167}
168impl MessageRead for AckMessage {
169    fn msg_code(&self) -> MsgCode {
170        MsgCode::Empty
171    }
172
173    fn msg_type(&self) -> MsgType {
174        MsgType::Ack
175    }
176
177    fn msg_id(&self) -> u16 {
178        0
179    }
180
181    fn msg_token(&self) -> MsgToken {
182        Default::default()
183    }
184
185    fn payload(&self) -> &[u8] {
186        Default::default()
187    }
188
189    fn content_format(&self) -> Option<ContentFormat> {
190        None
191    }
192
193    fn accept(&self) -> Option<ContentFormat> {
194        None
195    }
196
197    fn block2(&self) -> Option<BlockInfo> {
198        None
199    }
200
201    fn block1(&self) -> Option<BlockInfo> {
202        None
203    }
204
205    fn options(&self) -> OptionIterator<'_> {
206        Default::default()
207    }
208
209    fn write_msg_to(&self, target: &mut dyn MessageWrite) -> Result<(), Error> {
210        target.set_msg_code(MsgCode::Empty);
211        target.set_msg_type(MsgType::Ack);
212        target.set_msg_token(MsgToken::EMPTY);
213        Ok(())
214    }
215}