async_coap/message/
write.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::*;
17
18/// Trait for writing/serializing a CoAP message.
19pub trait MessageWrite: OptionInsert {
20    /// Sets the CoAP message type. This may be called at any time during message writing
21    /// without disrupting the operation. It may be called multiple times if necessary.
22    /// The written value is that of the last call.
23    fn set_msg_type(&mut self, tt: MsgType);
24
25    /// Sets the CoAP message id. This may be called at any time during message writing
26    /// without disrupting the operation. It may be called multiple times if necessary.
27    /// The written value is that of the last call.
28    fn set_msg_id(&mut self, msg_id: MsgId);
29
30    /// Sets the CoAP message code. This may be called at any time during message writing
31    /// without disrupting the operation. It may be called multiple times if necessary.
32    /// The written value is that of the last call.
33    fn set_msg_code(&mut self, code: MsgCode);
34
35    /// Sets the CoAP message token. Calling this method out-of-order will cause any previously
36    /// written options or payload to be lost. It may be called multiple times if necessary.
37    /// The written value is that of the last call.
38    fn set_msg_token(&mut self, token: MsgToken);
39
40    /// Appends bytes from the given slice `body` to the payload of the message.
41    /// This method should only be called after the token and all options have been set.
42    /// This method may be called multiple times, each time appending data to the payload.
43    fn append_payload_bytes(&mut self, body: &[u8]) -> Result<(), Error>;
44
45    /// Appends bytes from the UTF8 representation of the given string slice `body` to the payload
46    /// of the message.
47    /// This method should only be called after the token and all options have been set.
48    /// This method may be called multiple times, each time appending data to the payload.
49    fn append_payload_string(&mut self, body: &str) -> Result<(), Error> {
50        self.append_payload_bytes(body.as_bytes())
51    }
52
53    /// Appends a single byte to the payload of the message.
54    /// This method should only be called after the token and all options have been set.
55    /// This method may be called multiple times, each time appending data to the payload.
56    fn append_payload_u8(&mut self, b: u8) -> Result<(), Error> {
57        self.append_payload_bytes(&[b])
58    }
59
60    /// Appends the UTF8 representation for a single unicode character to the payload of the
61    /// message.
62    /// This method should only be called after the token and all options have been set.
63    /// This method may be called multiple times, each time appending data to the payload.
64    fn append_payload_char(&mut self, c: char) -> Result<(), Error> {
65        self.append_payload_string(c.encode_utf8(&mut [0; 4]))
66    }
67
68    /// Removes the message payload along with all options.
69    fn clear(&mut self);
70}
71
72impl<'a> core::fmt::Write for dyn MessageWrite + 'a {
73    fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
74        self.append_payload_string(s)?;
75        Ok(())
76    }
77
78    fn write_char(&mut self, c: char) -> Result<(), core::fmt::Error> {
79        self.append_payload_char(c)?;
80        Ok(())
81    }
82}
83
84impl<'a> std::io::Write for dyn MessageWrite + 'a {
85    fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
86        self.append_payload_bytes(buf)
87            .map(|_| buf.len())
88            .map_err(|_| std::io::ErrorKind::Other.into())
89    }
90
91    fn flush(&mut self) -> Result<(), std::io::Error> {
92        Ok(())
93    }
94
95    fn write_all(&mut self, buf: &[u8]) -> Result<(), std::io::Error> {
96        self.append_payload_bytes(buf)
97            .map_err(|_| std::io::ErrorKind::Other.into())
98    }
99}
100
101impl<'a> std::io::Write for BufferMessageEncoder<'a> {
102    fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
103        self.append_payload_bytes(buf)
104            .map(|_| buf.len())
105            .map_err(|_| std::io::ErrorKind::Other.into())
106    }
107
108    fn flush(&mut self) -> Result<(), std::io::Error> {
109        Ok(())
110    }
111
112    fn write_all(&mut self, buf: &[u8]) -> Result<(), std::io::Error> {
113        self.append_payload_bytes(buf)
114            .map_err(|_| std::io::ErrorKind::Other.into())
115    }
116}
117
118impl std::io::Write for VecMessageEncoder {
119    fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
120        self.append_payload_bytes(buf)
121            .map(|_| buf.len())
122            .map_err(|_| std::io::ErrorKind::Other.into())
123    }
124
125    fn flush(&mut self) -> Result<(), std::io::Error> {
126        Ok(())
127    }
128
129    fn write_all(&mut self, buf: &[u8]) -> Result<(), std::io::Error> {
130        self.append_payload_bytes(buf)
131            .map_err(|_| std::io::ErrorKind::Other.into())
132    }
133}