async_coap/message/
msg_code.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
16/// Enum representing the *class* of a CoAP message code.
17#[derive(Debug, Copy, Eq, PartialEq, Clone)]
18pub enum MsgCodeClass {
19    /// Class for methods
20    Method = 0,
21
22    /// Class for successful responses
23    Success = 2,
24
25    /// Class for client error responses
26    ClientError = 4,
27
28    /// Class for server error responses
29    ServerError = 5,
30
31    /// Class for in-band signaling
32    Signal = 7,
33}
34
35impl MsgCodeClass {
36    /// Tries to calculate the message code class from the given message code.
37    pub fn try_from(x: u8) -> Option<MsgCodeClass> {
38        match x {
39            0 => Some(MsgCodeClass::Method),
40            2 => Some(MsgCodeClass::Success),
41            4 => Some(MsgCodeClass::ClientError),
42            5 => Some(MsgCodeClass::ServerError),
43            7 => Some(MsgCodeClass::Signal),
44            _ => None,
45        }
46    }
47
48    /// Returns true if the given message code is in this message code class.
49    pub fn contains(self, code: MsgCode) -> bool {
50        let code_u8 = code as u8;
51
52        code_u8 != 0 && (code_u8 >> 5) == self as u8
53    }
54}
55
56/// Helper function
57const fn calc_code(class: u8, detail: u8) -> isize {
58    (((class & 0x7) << 5) + detail) as isize
59}
60
61/// Enum representing a CoAP message code.
62#[derive(Debug, Copy, Eq, PartialEq, Clone)]
63pub enum MsgCode {
64    /// Empty message code. Only used for ping requests, resets, and empty acknowledgements.
65    Empty = 0x00,
66
67    /// CoAP GET method.
68    MethodGet = 0x01,
69
70    /// CoAP POST method.
71    MethodPost = 0x02,
72
73    /// CoAP PUT method.
74    MethodPut = 0x03,
75
76    /// CoAP DELETE method.
77    MethodDelete = 0x04,
78
79    /// CoAP FETCH method.
80    MethodFetch = 0x05,
81
82    /// CoAP PATCH method.
83    MethodPatch = 0x06,
84
85    /// CoAP iPATCH method.
86    MethodIPatch = 0x07,
87
88    /// CoAP CREATED success code.
89    SuccessCreated = 0x41,
90
91    /// CoAP DELETED success code.
92    SuccessDeleted = 0x42,
93
94    /// CoAP VALID success code.
95    SuccessValid = 0x43,
96
97    /// CoAP CHANGED success code.
98    SuccessChanged = 0x44,
99
100    /// CoAP CONTENT success code.
101    SuccessContent = 0x45,
102
103    /// CoAP CONTINUE success code.
104    SuccessContinue = 0x5F,
105
106    /// CoAP BAD_REQUEST client error.
107    ClientErrorBadRequest = 0x80,
108
109    /// CoAP UNAUTHORIZED client error.
110    ClientErrorUnauthorized = 0x81,
111
112    /// CoAP BAD_OPTION client error.
113    ClientErrorBadOption = 0x82,
114
115    /// CoAP FORBIDDEN client error.
116    ClientErrorForbidden = 0x83,
117
118    /// CoAP NOT_FOUND client error.
119    ClientErrorNotFound = 0x84,
120
121    /// CoAP METHOD_NOT_ALLOWED client error.
122    ClientErrorMethodNotAllowed = 0x85,
123
124    /// CoAP NOT_ACCEPTABLE client error.
125    ClientErrorNotAcceptable = 0x86,
126
127    /// CoAP REQUEST_ENTITY_INCOMPLETE client error.
128    ClientErrorRequestEntityIncomplete = 0x88,
129
130    /// CoAP PRECONDITION_FAILED client error.
131    ClientErrorPreconditionFailed = 0x8C,
132
133    /// CoAP REQUEST_ENTITY_TOO_LARGE client error.
134    ClientErrorRequestEntityTooLarge = 0x8D,
135
136    /// CoAP UNSUPPORTED_MEDIA_TYPE client error.
137    ClientErrorUnsupportedMediaType = 0x8F,
138
139    /// RFC8516 "Too Many Requests" Response Code for the Constrained Application Protocol
140    ClientErrorTooManyRequests = calc_code(4, 29),
141
142    /// CoAP INTERNAL_SERVER_ERROR server error.
143    ServerErrorInternalServerError = 0xA0,
144
145    /// CoAP NOT_IMPLEMENTED server error.
146    ServerErrorNotImplemented = 0xA1,
147
148    /// CoAP BAD_GATEWAY server error.
149    ServerErrorBadGateway = 0xA2,
150
151    /// CoAP SERVICE_UNAVAILABLE server error.
152    ServerErrorServiceUnavailable = 0xA3,
153
154    /// CoAP GATEWAY_TIMEOUT server error.
155    ServerErrorGatewayTimeout = 0xA4,
156
157    /// CoAP PROXYING_NOT_SUPPORTED server error.
158    ServerErrorProxyingNotSupported = 0xA5,
159
160    /// CoAP CSM in-band signal.
161    SignalCsm = 0xE1,
162
163    /// CoAP PING in-band signal.
164    SignalPing = 0xE2,
165
166    /// CoAP PONG in-band signal.
167    SignalPong = 0xE3,
168
169    /// CoAP RELEASE in-band signal.
170    SignalRelease = 0xE4,
171
172    /// CoAP ABORT in-band signal.
173    SignalAbort = 0xE5,
174}
175
176impl MsgCode {
177    /// Tries to convert the given `u8` into a `MsgCode`. If the given code isn't recognized,
178    /// this method will return `None`.
179    pub fn try_from(x: u8) -> Option<MsgCode> {
180        use MsgCode::*;
181        match x {
182            0x00 => Some(Empty),
183            0x01 => Some(MethodGet),
184            0x02 => Some(MethodPost),
185            0x03 => Some(MethodPut),
186            0x04 => Some(MethodDelete),
187
188            0x41 => Some(SuccessCreated),
189            0x42 => Some(SuccessDeleted),
190            0x43 => Some(SuccessValid),
191            0x44 => Some(SuccessChanged),
192            0x45 => Some(SuccessContent),
193            0x5F => Some(SuccessContinue),
194
195            0x80 => Some(ClientErrorBadRequest),
196            0x81 => Some(ClientErrorUnauthorized),
197            0x82 => Some(ClientErrorBadOption),
198            0x83 => Some(ClientErrorForbidden),
199            0x84 => Some(ClientErrorNotFound),
200            0x85 => Some(ClientErrorMethodNotAllowed),
201            0x86 => Some(ClientErrorNotAcceptable),
202            0x88 => Some(ClientErrorRequestEntityIncomplete),
203            0x8C => Some(ClientErrorPreconditionFailed),
204            0x8D => Some(ClientErrorRequestEntityTooLarge),
205            0x8F => Some(ClientErrorUnsupportedMediaType),
206            0x9D => Some(ClientErrorTooManyRequests),
207
208            0xA0 => Some(ServerErrorInternalServerError),
209            0xA1 => Some(ServerErrorNotImplemented),
210            0xA2 => Some(ServerErrorBadGateway),
211            0xA3 => Some(ServerErrorServiceUnavailable),
212            0xA4 => Some(ServerErrorGatewayTimeout),
213            0xA5 => Some(ServerErrorProxyingNotSupported),
214
215            0xE1 => Some(SignalCsm),
216            0xE2 => Some(SignalPing),
217            0xE3 => Some(SignalPong),
218            0xE4 => Some(SignalRelease),
219            0xE5 => Some(SignalAbort),
220
221            _ => None,
222        }
223    }
224
225    /// Returns an approximation of this message code as an HTTP status code.
226    pub fn to_http_code(self) -> u16 {
227        ((self as u8) >> 5) as u16 * 100 + (self as u8 as u16) & 0b11111
228    }
229
230    /// Returns true if this is the empty code.
231    pub fn is_empty(self) -> bool {
232        self as u8 == 0
233    }
234
235    /// Returns true if message code is a method.
236    pub fn is_method(self) -> bool {
237        MsgCodeClass::Method.contains(self)
238    }
239
240    /// Returns true if message code is a client error.
241    pub fn is_client_error(self) -> bool {
242        MsgCodeClass::ClientError.contains(self)
243    }
244
245    /// Returns true if message code is a server error.
246    pub fn is_server_error(self) -> bool {
247        MsgCodeClass::ServerError.contains(self)
248    }
249
250    /// Returns true if message code is any sort of error.
251    pub fn is_error(self) -> bool {
252        self.is_client_error() || self.is_server_error()
253    }
254
255    /// Returns true if message code indicates success.
256    pub fn is_success(self) -> bool {
257        MsgCodeClass::Success.contains(self)
258    }
259
260    /// Returns true if message code is an in-band signal.
261    pub fn is_signal(self) -> bool {
262        MsgCodeClass::Signal.contains(self)
263    }
264}
265
266impl Default for MsgCode {
267    fn default() -> Self {
268        MsgCode::Empty
269    }
270}
271
272impl core::convert::From<MsgCode> for u8 {
273    fn from(code: MsgCode) -> Self {
274        code as u8
275    }
276}
277
278impl core::convert::From<MsgCode> for u16 {
279    fn from(code: MsgCode) -> Self {
280        code as u16
281    }
282}
283
284impl core::convert::From<MsgCode> for u32 {
285    fn from(code: MsgCode) -> Self {
286        code as u32
287    }
288}