1use std::{
14 ffi::CStr,
15 fmt::{Display, Formatter},
16};
17
18use libcoap_sys::{
19 coap_option_num_t, coap_pdu_code_t, coap_pdu_code_t_COAP_EMPTY_CODE, coap_pdu_code_t_COAP_REQUEST_CODE_DELETE,
20 coap_pdu_code_t_COAP_REQUEST_CODE_FETCH, coap_pdu_code_t_COAP_REQUEST_CODE_GET,
21 coap_pdu_code_t_COAP_REQUEST_CODE_IPATCH, coap_pdu_code_t_COAP_REQUEST_CODE_PATCH,
22 coap_pdu_code_t_COAP_REQUEST_CODE_POST, coap_pdu_code_t_COAP_REQUEST_CODE_PUT,
23 coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_GATEWAY, coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_OPTION,
24 coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_REQUEST, coap_pdu_code_t_COAP_RESPONSE_CODE_CHANGED,
25 coap_pdu_code_t_COAP_RESPONSE_CODE_CONFLICT, coap_pdu_code_t_COAP_RESPONSE_CODE_CONTENT,
26 coap_pdu_code_t_COAP_RESPONSE_CODE_CONTINUE, coap_pdu_code_t_COAP_RESPONSE_CODE_CREATED,
27 coap_pdu_code_t_COAP_RESPONSE_CODE_DELETED, coap_pdu_code_t_COAP_RESPONSE_CODE_FORBIDDEN,
28 coap_pdu_code_t_COAP_RESPONSE_CODE_GATEWAY_TIMEOUT, coap_pdu_code_t_COAP_RESPONSE_CODE_HOP_LIMIT_REACHED,
29 coap_pdu_code_t_COAP_RESPONSE_CODE_INCOMPLETE, coap_pdu_code_t_COAP_RESPONSE_CODE_INTERNAL_ERROR,
30 coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_ACCEPTABLE, coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_ALLOWED,
31 coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_FOUND, coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_IMPLEMENTED,
32 coap_pdu_code_t_COAP_RESPONSE_CODE_PRECONDITION_FAILED, coap_pdu_code_t_COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED,
33 coap_pdu_code_t_COAP_RESPONSE_CODE_REQUEST_TOO_LARGE, coap_pdu_code_t_COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE,
34 coap_pdu_code_t_COAP_RESPONSE_CODE_TOO_MANY_REQUESTS, coap_pdu_code_t_COAP_RESPONSE_CODE_UNAUTHORIZED,
35 coap_pdu_code_t_COAP_RESPONSE_CODE_UNPROCESSABLE, coap_pdu_code_t_COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT,
36 coap_pdu_code_t_COAP_RESPONSE_CODE_VALID, coap_pdu_type_t, coap_pdu_type_t_COAP_MESSAGE_ACK,
37 coap_pdu_type_t_COAP_MESSAGE_CON, coap_pdu_type_t_COAP_MESSAGE_NON, coap_pdu_type_t_COAP_MESSAGE_RST,
38 coap_request_t, coap_request_t_COAP_REQUEST_DELETE, coap_request_t_COAP_REQUEST_FETCH,
39 coap_request_t_COAP_REQUEST_GET, coap_request_t_COAP_REQUEST_IPATCH, coap_request_t_COAP_REQUEST_PATCH,
40 coap_request_t_COAP_REQUEST_POST, coap_request_t_COAP_REQUEST_PUT, coap_response_phrase,
41 COAP_MEDIATYPE_APPLICATION_ACE_CBOR, COAP_MEDIATYPE_APPLICATION_CBOR, COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON,
42 COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0,
43 COAP_MEDIATYPE_APPLICATION_COSE_KEY, COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, COAP_MEDIATYPE_APPLICATION_COSE_MAC,
44 COAP_MEDIATYPE_APPLICATION_COSE_MAC0, COAP_MEDIATYPE_APPLICATION_COSE_SIGN, COAP_MEDIATYPE_APPLICATION_COSE_SIGN1,
45 COAP_MEDIATYPE_APPLICATION_CWT, COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, COAP_MEDIATYPE_APPLICATION_EXI,
46 COAP_MEDIATYPE_APPLICATION_JSON, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ,
47 COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, COAP_MEDIATYPE_APPLICATION_OSCORE, COAP_MEDIATYPE_APPLICATION_RDF_XML,
48 COAP_MEDIATYPE_APPLICATION_SENML_CBOR, COAP_MEDIATYPE_APPLICATION_SENML_EXI, COAP_MEDIATYPE_APPLICATION_SENML_JSON,
49 COAP_MEDIATYPE_APPLICATION_SENML_XML, COAP_MEDIATYPE_APPLICATION_SENSML_CBOR,
50 COAP_MEDIATYPE_APPLICATION_SENSML_EXI, COAP_MEDIATYPE_APPLICATION_SENSML_JSON,
51 COAP_MEDIATYPE_APPLICATION_SENSML_XML, COAP_MEDIATYPE_APPLICATION_XML, COAP_MEDIATYPE_TEXT_PLAIN,
52 COAP_OPTION_ACCEPT, COAP_OPTION_BLOCK1, COAP_OPTION_BLOCK2, COAP_OPTION_CONTENT_FORMAT, COAP_OPTION_ECHO,
53 COAP_OPTION_ETAG, COAP_OPTION_HOP_LIMIT, COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH,
54 COAP_OPTION_LOCATION_PATH, COAP_OPTION_LOCATION_QUERY, COAP_OPTION_MAXAGE, COAP_OPTION_NORESPONSE,
55 COAP_OPTION_OBSERVE, COAP_OPTION_OSCORE, COAP_OPTION_PROXY_SCHEME, COAP_OPTION_PROXY_URI, COAP_OPTION_Q_BLOCK1,
56 COAP_OPTION_Q_BLOCK2, COAP_OPTION_RTAG, COAP_OPTION_SIZE1, COAP_OPTION_SIZE2, COAP_OPTION_URI_HOST,
57 COAP_OPTION_URI_PATH, COAP_OPTION_URI_PORT, COAP_OPTION_URI_QUERY,
58};
59use num_derive::FromPrimitive;
60use num_traits::FromPrimitive;
61
62use crate::error::{MessageCodeError, UnknownOptionError};
63
64pub type ETag = Box<[u8]>;
65pub type MaxAge = u32;
66pub type LocationPath = String;
67pub type LocationQuery = String;
68pub type UriHost = String;
69pub type UriPort = u16;
70pub type UriPath = String;
71pub type UriQuery = String;
72pub type ContentFormat = u16;
73pub type ProxyUri = String;
74pub type ProxyScheme = String;
75pub type Size = u32;
76pub type Block = u32;
77pub type HopLimit = u16;
78pub type NoResponse = u8;
79pub type Observe = u32;
80pub type Oscore = Box<[u8]>;
82pub type Echo = Box<[u8]>;
83pub type RequestTag = Box<[u8]>;
84
85pub type CoapOptionNum = coap_option_num_t;
86pub type CoapToken = Box<[u8]>;
87
88#[derive(Clone, Debug, Eq, PartialEq, Hash)]
91pub enum CoapMatch {
92 ETag(ETag),
93 Empty,
94}
95
96#[repr(u16)]
105#[non_exhaustive]
106#[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq, Hash)]
107pub enum CoapOptionType {
108 IfMatch = COAP_OPTION_IF_MATCH as u16,
110 UriHost = COAP_OPTION_URI_HOST as u16,
112 ETag = COAP_OPTION_ETAG as u16,
114 IfNoneMatch = COAP_OPTION_IF_NONE_MATCH as u16,
116 Observe = COAP_OPTION_OBSERVE as u16,
118 UriPort = COAP_OPTION_URI_PORT as u16,
120 LocationPath = COAP_OPTION_LOCATION_PATH as u16,
122 Oscore = COAP_OPTION_OSCORE as u16,
124 UriPath = COAP_OPTION_URI_PATH as u16,
126 ContentFormat = COAP_OPTION_CONTENT_FORMAT as u16,
128 MaxAge = COAP_OPTION_MAXAGE as u16,
130 UriQuery = COAP_OPTION_URI_QUERY as u16,
132 HopLimit = COAP_OPTION_HOP_LIMIT as u16,
134 Accept = COAP_OPTION_ACCEPT as u16,
136 QBlock1 = COAP_OPTION_Q_BLOCK1 as u16,
138 LocationQuery = COAP_OPTION_LOCATION_QUERY as u16,
140 Block2 = COAP_OPTION_BLOCK2 as u16,
142 Block1 = COAP_OPTION_BLOCK1 as u16,
144 Size2 = COAP_OPTION_SIZE2 as u16,
146 QBlock2 = COAP_OPTION_Q_BLOCK2 as u16,
148 ProxyUri = COAP_OPTION_PROXY_URI as u16,
150 ProxyScheme = COAP_OPTION_PROXY_SCHEME as u16,
152 Size1 = COAP_OPTION_SIZE1 as u16,
154 Echo = COAP_OPTION_ECHO as u16,
156 NoResponse = COAP_OPTION_NORESPONSE as u16,
158 RTag = COAP_OPTION_RTAG as u16,
160}
161
162impl CoapOptionType {
163 pub fn to_raw_option_num(self) -> coap_option_num_t {
165 self as u16
166 }
167
168 pub fn max_len(&self) -> usize {
170 match self {
171 CoapOptionType::IfMatch => 8,
172 CoapOptionType::UriHost => 255,
173 CoapOptionType::ETag => 8,
174 CoapOptionType::IfNoneMatch => 0,
175 CoapOptionType::UriPort => 2,
176 CoapOptionType::LocationPath => 255,
177 CoapOptionType::UriPath => 255,
178 CoapOptionType::ContentFormat => 2,
179 CoapOptionType::MaxAge => 4,
180 CoapOptionType::UriQuery => 255,
181 CoapOptionType::Accept => 2,
182 CoapOptionType::LocationQuery => 255,
183 CoapOptionType::ProxyUri => 1034,
184 CoapOptionType::ProxyScheme => 255,
185 CoapOptionType::Size1 => 4,
186 CoapOptionType::Size2 => 4,
187 CoapOptionType::Block1 => 3,
188 CoapOptionType::Block2 => 3,
189 CoapOptionType::HopLimit => 1,
190 CoapOptionType::NoResponse => 1,
191 CoapOptionType::Observe => 3,
192 CoapOptionType::Oscore => 255,
193 CoapOptionType::Echo => 40,
194 CoapOptionType::RTag => 8,
195 CoapOptionType::QBlock1 => 3,
196 CoapOptionType::QBlock2 => 3,
197 }
198 }
199
200 pub fn min_len(&self) -> usize {
202 match self {
203 CoapOptionType::IfMatch => 0,
204 CoapOptionType::UriHost => 1,
205 CoapOptionType::ETag => 1,
206 CoapOptionType::IfNoneMatch => 0,
207 CoapOptionType::UriPort => 0,
208 CoapOptionType::LocationPath => 0,
209 CoapOptionType::UriPath => 0,
210 CoapOptionType::ContentFormat => 0,
211 CoapOptionType::MaxAge => 0,
212 CoapOptionType::UriQuery => 0,
213 CoapOptionType::Accept => 0,
214 CoapOptionType::LocationQuery => 0,
215 CoapOptionType::ProxyUri => 1,
216 CoapOptionType::ProxyScheme => 1,
217 CoapOptionType::Size1 => 0,
218 CoapOptionType::Size2 => 0,
219 CoapOptionType::Block1 => 0,
220 CoapOptionType::Block2 => 0,
221 CoapOptionType::HopLimit => 1,
222 CoapOptionType::NoResponse => 0,
223 CoapOptionType::Observe => 0,
224 CoapOptionType::Oscore => 0,
225 CoapOptionType::Echo => 1,
226 CoapOptionType::RTag => 0,
227 CoapOptionType::QBlock1 => 0,
228 CoapOptionType::QBlock2 => 0,
229 }
230 }
231}
232
233impl TryFrom<coap_option_num_t> for CoapOptionType {
234 type Error = UnknownOptionError;
235
236 fn try_from(num: coap_option_num_t) -> Result<Self, Self::Error> {
237 <CoapOptionType as FromPrimitive>::from_u16(num).ok_or(UnknownOptionError::Unknown)
238 }
239}
240
241#[repr(u16)]
248#[derive(Copy, Clone, FromPrimitive, Eq, PartialEq, Hash, Debug)]
249#[non_exhaustive]
250pub enum CoapContentFormat {
251 Cbor = COAP_MEDIATYPE_APPLICATION_CBOR as u16,
252 DotsCbor = COAP_MEDIATYPE_APPLICATION_DOTS_CBOR as u16,
253 SenMlCbor = COAP_MEDIATYPE_APPLICATION_SENML_CBOR as u16,
254 SenMlExi = COAP_MEDIATYPE_APPLICATION_SENML_EXI as u16,
255 CoseEncrypt = COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT as u16,
256 CoseEncrypt0 = COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0 as u16,
257 CoseKey = COAP_MEDIATYPE_APPLICATION_COSE_KEY as u16,
258 CoseKeySet = COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET as u16,
259 CoseMac = COAP_MEDIATYPE_APPLICATION_COSE_MAC as u16,
260 CoseMac0 = COAP_MEDIATYPE_APPLICATION_COSE_MAC0 as u16,
261 CoseSign = COAP_MEDIATYPE_APPLICATION_COSE_SIGN as u16,
262 CoseSign1 = COAP_MEDIATYPE_APPLICATION_COSE_SIGN1 as u16,
263 Cwt = COAP_MEDIATYPE_APPLICATION_CWT as u16,
264 Exi = COAP_MEDIATYPE_APPLICATION_EXI as u16,
265 Json = COAP_MEDIATYPE_APPLICATION_JSON as u16,
266 LinkFormat = COAP_MEDIATYPE_APPLICATION_LINK_FORMAT as u16,
267 OctetStream = COAP_MEDIATYPE_APPLICATION_OCTET_STREAM as u16,
268 RdfXml = COAP_MEDIATYPE_APPLICATION_RDF_XML as u16,
269 SenMlJson = COAP_MEDIATYPE_APPLICATION_SENML_JSON as u16,
270 SenMlXml = COAP_MEDIATYPE_APPLICATION_SENML_XML as u16,
271 SensMlCbor = COAP_MEDIATYPE_APPLICATION_SENSML_CBOR as u16,
272 SensMlExi = COAP_MEDIATYPE_APPLICATION_SENSML_EXI as u16,
273 SensMlJson = COAP_MEDIATYPE_APPLICATION_SENSML_JSON as u16,
274 SensMlXml = COAP_MEDIATYPE_APPLICATION_SENSML_XML as u16,
275 ApplicationXml = COAP_MEDIATYPE_APPLICATION_XML as u16,
276 TextPlain = COAP_MEDIATYPE_TEXT_PLAIN as u16,
277 AceCbor = COAP_MEDIATYPE_APPLICATION_ACE_CBOR as u16,
278 CoapGroupJson = COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON as u16,
279 MbCborSeq = COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ as u16,
280 Oscore = COAP_MEDIATYPE_APPLICATION_OSCORE as u16,
281 Other,
282}
283
284impl From<ContentFormat> for CoapContentFormat {
285 fn from(value: u16) -> Self {
286 <CoapContentFormat as FromPrimitive>::from_u16(value).unwrap_or(CoapContentFormat::Other)
287 }
288}
289
290#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
296#[repr(u8)]
297pub enum CoapMessageCode {
298 Empty,
299 Request(CoapRequestCode),
300 Response(CoapResponseCode),
301}
302
303impl CoapMessageCode {
304 pub fn to_raw_pdu_code(self) -> coap_pdu_code_t {
307 match self {
308 CoapMessageCode::Empty => coap_pdu_code_t_COAP_EMPTY_CODE,
309 CoapMessageCode::Request(req) => req.to_raw_pdu_code(),
310 CoapMessageCode::Response(rsp) => rsp.to_raw_pdu_code(),
311 }
312 }
313}
314
315impl From<CoapRequestCode> for CoapMessageCode {
316 fn from(code: CoapRequestCode) -> Self {
317 CoapMessageCode::Request(code)
318 }
319}
320
321impl From<CoapResponseCode> for CoapMessageCode {
322 fn from(code: CoapResponseCode) -> Self {
323 CoapMessageCode::Response(code)
324 }
325}
326
327impl TryFrom<coap_pdu_code_t> for CoapMessageCode {
328 type Error = MessageCodeError;
329
330 fn try_from(code: coap_pdu_code_t) -> Result<Self, Self::Error> {
331 #[allow(non_upper_case_globals)]
334 match code {
335 coap_pdu_code_t_COAP_EMPTY_CODE => Ok(CoapMessageCode::Empty),
336 code => CoapRequestCode::try_from(code)
337 .map(CoapMessageCode::Request)
338 .or_else(|_| CoapResponseCode::try_from(code).map(CoapMessageCode::Response)),
339 }
340 }
341}
342
343#[repr(u8)]
348#[non_exhaustive]
349#[derive(FromPrimitive, Clone, Copy, Eq, PartialEq, Hash, Debug)]
350pub enum CoapRequestCode {
351 Get = coap_pdu_code_t_COAP_REQUEST_CODE_GET as u8,
352 Put = coap_pdu_code_t_COAP_REQUEST_CODE_PUT as u8,
353 Delete = coap_pdu_code_t_COAP_REQUEST_CODE_DELETE as u8,
354 Post = coap_pdu_code_t_COAP_REQUEST_CODE_POST as u8,
355 Fetch = coap_pdu_code_t_COAP_REQUEST_CODE_FETCH as u8,
356 IPatch = coap_pdu_code_t_COAP_REQUEST_CODE_IPATCH as u8,
357 Patch = coap_pdu_code_t_COAP_REQUEST_CODE_PATCH as u8,
358}
359
360impl CoapRequestCode {
361 pub fn to_raw_request(self) -> coap_request_t {
367 match self {
368 CoapRequestCode::Get => coap_request_t_COAP_REQUEST_GET,
369 CoapRequestCode::Put => coap_request_t_COAP_REQUEST_PUT,
370 CoapRequestCode::Delete => coap_request_t_COAP_REQUEST_DELETE,
371 CoapRequestCode::Post => coap_request_t_COAP_REQUEST_POST,
372 CoapRequestCode::Fetch => coap_request_t_COAP_REQUEST_FETCH,
373 CoapRequestCode::IPatch => coap_request_t_COAP_REQUEST_IPATCH,
374 CoapRequestCode::Patch => coap_request_t_COAP_REQUEST_PATCH,
375 }
376 }
377
378 pub fn to_raw_pdu_code(self) -> coap_pdu_code_t {
381 match self {
382 CoapRequestCode::Get => coap_pdu_code_t_COAP_REQUEST_CODE_GET,
383 CoapRequestCode::Put => coap_pdu_code_t_COAP_REQUEST_CODE_PUT,
384 CoapRequestCode::Delete => coap_pdu_code_t_COAP_REQUEST_CODE_FETCH,
385 CoapRequestCode::Post => coap_pdu_code_t_COAP_REQUEST_CODE_POST,
386 CoapRequestCode::Fetch => coap_pdu_code_t_COAP_REQUEST_CODE_FETCH,
387 CoapRequestCode::IPatch => coap_pdu_code_t_COAP_REQUEST_CODE_IPATCH,
388 CoapRequestCode::Patch => coap_pdu_code_t_COAP_REQUEST_CODE_PATCH,
389 }
390 }
391}
392
393impl TryFrom<coap_pdu_code_t> for CoapRequestCode {
394 type Error = MessageCodeError;
395
396 fn try_from(value: coap_pdu_code_t) -> Result<Self, Self::Error> {
397 <CoapRequestCode as FromPrimitive>::from_u32(value as u32).ok_or(MessageCodeError::NotARequestCode)
398 }
399}
400
401#[repr(u8)]
406#[non_exhaustive]
407#[derive(Clone, Copy, FromPrimitive, Debug, Eq, PartialEq, Hash)]
408pub enum CoapResponseCode {
409 Content = coap_pdu_code_t_COAP_RESPONSE_CODE_CONTENT as u8,
410 BadGateway = coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_GATEWAY as u8,
411 Continue = coap_pdu_code_t_COAP_RESPONSE_CODE_CONTINUE as u8,
412 Conflict = coap_pdu_code_t_COAP_RESPONSE_CODE_CONFLICT as u8,
413 BadRequest = coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_REQUEST as u8,
414 BadOption = coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_OPTION as u8,
415 Changed = coap_pdu_code_t_COAP_RESPONSE_CODE_CHANGED as u8,
416 Created = coap_pdu_code_t_COAP_RESPONSE_CODE_CREATED as u8,
417 Deleted = coap_pdu_code_t_COAP_RESPONSE_CODE_DELETED as u8,
418 Forbidden = coap_pdu_code_t_COAP_RESPONSE_CODE_FORBIDDEN as u8,
419 GatewayTimeout = coap_pdu_code_t_COAP_RESPONSE_CODE_GATEWAY_TIMEOUT as u8,
420 HopLimitReached = coap_pdu_code_t_COAP_RESPONSE_CODE_HOP_LIMIT_REACHED as u8,
421 Incomplete = coap_pdu_code_t_COAP_RESPONSE_CODE_INCOMPLETE as u8,
422 InternalError = coap_pdu_code_t_COAP_RESPONSE_CODE_INTERNAL_ERROR as u8,
423 NotAcceptable = coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_ACCEPTABLE as u8,
424 NotAllowed = coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_ALLOWED as u8,
425 NotFound = coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_FOUND as u8,
426 NotImplemented = coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_IMPLEMENTED as u8,
427 PreconditionFailed = coap_pdu_code_t_COAP_RESPONSE_CODE_PRECONDITION_FAILED as u8,
428 ProxyingNotSupported = coap_pdu_code_t_COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED as u8,
429 RequestTooLarge = coap_pdu_code_t_COAP_RESPONSE_CODE_REQUEST_TOO_LARGE as u8,
430 ServiceUnavailable = coap_pdu_code_t_COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE as u8,
431 TooManyRequests = coap_pdu_code_t_COAP_RESPONSE_CODE_TOO_MANY_REQUESTS as u8,
432 Unauthorized = coap_pdu_code_t_COAP_RESPONSE_CODE_UNAUTHORIZED as u8,
433 Unprocessable = coap_pdu_code_t_COAP_RESPONSE_CODE_UNPROCESSABLE as u8,
434 UnsupportedContentFormat = coap_pdu_code_t_COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT as u8,
435 Valid = coap_pdu_code_t_COAP_RESPONSE_CODE_VALID as u8,
436}
437
438impl CoapResponseCode {
439 pub fn to_raw_pdu_code(self) -> coap_pdu_code_t {
442 match self {
443 CoapResponseCode::Content => coap_pdu_code_t_COAP_RESPONSE_CODE_CONTENT,
444 CoapResponseCode::BadGateway => coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_GATEWAY,
445 CoapResponseCode::Continue => coap_pdu_code_t_COAP_RESPONSE_CODE_CONTINUE,
446 CoapResponseCode::Conflict => coap_pdu_code_t_COAP_RESPONSE_CODE_CONFLICT,
447 CoapResponseCode::BadRequest => coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_REQUEST,
448 CoapResponseCode::BadOption => coap_pdu_code_t_COAP_RESPONSE_CODE_BAD_OPTION,
449 CoapResponseCode::Changed => coap_pdu_code_t_COAP_RESPONSE_CODE_CHANGED,
450 CoapResponseCode::Created => coap_pdu_code_t_COAP_RESPONSE_CODE_CREATED,
451 CoapResponseCode::Deleted => coap_pdu_code_t_COAP_RESPONSE_CODE_DELETED,
452 CoapResponseCode::Forbidden => coap_pdu_code_t_COAP_RESPONSE_CODE_FORBIDDEN,
453 CoapResponseCode::GatewayTimeout => coap_pdu_code_t_COAP_RESPONSE_CODE_GATEWAY_TIMEOUT,
454 CoapResponseCode::HopLimitReached => coap_pdu_code_t_COAP_RESPONSE_CODE_HOP_LIMIT_REACHED,
455 CoapResponseCode::Incomplete => coap_pdu_code_t_COAP_RESPONSE_CODE_INCOMPLETE,
456 CoapResponseCode::InternalError => coap_pdu_code_t_COAP_RESPONSE_CODE_INTERNAL_ERROR,
457 CoapResponseCode::NotAcceptable => coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_ACCEPTABLE,
458 CoapResponseCode::NotAllowed => coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_ALLOWED,
459 CoapResponseCode::NotFound => coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_FOUND,
460 CoapResponseCode::NotImplemented => coap_pdu_code_t_COAP_RESPONSE_CODE_NOT_IMPLEMENTED,
461 CoapResponseCode::PreconditionFailed => coap_pdu_code_t_COAP_RESPONSE_CODE_PRECONDITION_FAILED,
462 CoapResponseCode::ProxyingNotSupported => coap_pdu_code_t_COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED,
463 CoapResponseCode::RequestTooLarge => coap_pdu_code_t_COAP_RESPONSE_CODE_REQUEST_TOO_LARGE,
464 CoapResponseCode::ServiceUnavailable => coap_pdu_code_t_COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE,
465 CoapResponseCode::TooManyRequests => coap_pdu_code_t_COAP_RESPONSE_CODE_TOO_MANY_REQUESTS,
466 CoapResponseCode::Unauthorized => coap_pdu_code_t_COAP_RESPONSE_CODE_UNAUTHORIZED,
467 CoapResponseCode::Unprocessable => coap_pdu_code_t_COAP_RESPONSE_CODE_UNPROCESSABLE,
468 CoapResponseCode::UnsupportedContentFormat => coap_pdu_code_t_COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT,
469 CoapResponseCode::Valid => coap_pdu_code_t_COAP_RESPONSE_CODE_VALID,
470 }
471 }
472}
473
474impl Display for CoapResponseCode {
475 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
476 let response_phrase = unsafe {
477 let raw_phrase = coap_response_phrase(*self as u8);
478 if raw_phrase.is_null() {
479 "unknown response code"
480 } else {
481 CStr::from_ptr(raw_phrase)
482 .to_str()
483 .unwrap_or("unable to retrieve phrase for response code")
484 }
485 };
486
487 write!(f, "{}", response_phrase)
488 }
489}
490
491impl TryFrom<coap_pdu_code_t> for CoapResponseCode {
492 type Error = MessageCodeError;
493
494 fn try_from(value: coap_pdu_code_t) -> Result<Self, Self::Error> {
495 <CoapResponseCode as FromPrimitive>::from_u32(value as u32).ok_or(MessageCodeError::NotAResponseCode)
496 }
497}
498
499#[repr(u8)]
502#[derive(Copy, Clone, Hash, Eq, PartialEq, FromPrimitive, Debug)]
503pub enum CoapMessageType {
504 Con = coap_pdu_type_t_COAP_MESSAGE_CON as u8,
506 Non = coap_pdu_type_t_COAP_MESSAGE_NON as u8,
508 Ack = coap_pdu_type_t_COAP_MESSAGE_ACK as u8,
510 Rst = coap_pdu_type_t_COAP_MESSAGE_RST as u8,
512}
513
514impl CoapMessageType {
515 pub fn to_raw_pdu_type(&self) -> coap_pdu_type_t {
518 match self {
519 CoapMessageType::Con => coap_pdu_type_t_COAP_MESSAGE_CON,
520 CoapMessageType::Non => coap_pdu_type_t_COAP_MESSAGE_NON,
521 CoapMessageType::Ack => coap_pdu_type_t_COAP_MESSAGE_ACK,
522 CoapMessageType::Rst => coap_pdu_type_t_COAP_MESSAGE_RST,
523 }
524 }
525}
526
527impl From<coap_pdu_type_t> for CoapMessageType {
528 fn from(raw_type: coap_pdu_type_t) -> Self {
529 FromPrimitive::from_u32(raw_type as u32).expect("unknown PDU type")
530 }
531}