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}