1use alloc::{
4 borrow::ToOwned,
5 string::{String, ToString},
6};
7use core::{fmt, num::TryFromIntError};
8#[cfg(feature = "std")]
9use std::error;
10
11use crate::ResponseType;
12
13#[derive(Debug, PartialEq)]
15pub enum MessageError {
16 InvalidHeader,
17 InvalidPacketLength,
18 InvalidTokenLength,
19 InvalidOptionDelta,
20 InvalidOptionLength,
21}
22
23impl fmt::Display for MessageError {
24 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25 match self {
26 MessageError::InvalidHeader => {
27 write!(f, "CoAP error: invalid header")
28 }
29 MessageError::InvalidPacketLength => {
30 write!(f, "CoAP error: invalid packet length, consider using BlockHandler")
31 }
32 MessageError::InvalidTokenLength => {
33 write!(f, "CoAP error: invalid token length")
34 }
35 MessageError::InvalidOptionDelta => {
36 write!(f, "CoAP error: invalid option delta")
37 }
38 MessageError::InvalidOptionLength => {
39 write!(f, "CoAP error: invalid option length")
40 }
41 }
42 }
43}
44
45#[cfg(feature = "std")]
46impl error::Error for MessageError {}
47
48#[derive(Debug, PartialEq)]
50pub struct InvalidContentFormat;
51
52impl fmt::Display for InvalidContentFormat {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 write!(f, "CoAP error: invalid content-format number")
55 }
56}
57
58#[cfg(feature = "std")]
59impl error::Error for InvalidContentFormat {}
60
61#[derive(Debug, PartialEq)]
63pub struct InvalidObserve;
64
65impl fmt::Display for InvalidObserve {
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 write!(f, "CoAP error: invalid observe option number")
68 }
69}
70
71#[cfg(feature = "std")]
72impl error::Error for InvalidObserve {}
73
74#[derive(Debug, PartialEq)]
76pub struct IncompatibleOptionValueFormat {
77 pub message: String,
78}
79
80impl fmt::Display for IncompatibleOptionValueFormat {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 write!(f, "Incompatible option value: {}", self.message)
83 }
84}
85
86#[cfg(feature = "std")]
87impl error::Error for IncompatibleOptionValueFormat {}
88
89#[derive(Debug, PartialEq)]
91pub enum InvalidBlockValue {
92 SizeExponentEncodingError(usize),
93 TypeBoundsError(TryFromIntError),
94}
95
96impl fmt::Display for InvalidBlockValue {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 match self {
99 InvalidBlockValue::SizeExponentEncodingError(size) => {
100 write!(f, "size cannot be encoded {}", size)
101 }
102 InvalidBlockValue::TypeBoundsError(err) => {
103 write!(f, "size provided is outside type bounds: {}", err)
104 }
105 }
106 }
107}
108
109#[cfg(feature = "std")]
110impl error::Error for InvalidBlockValue {}
111
112#[derive(Debug, Clone)]
119pub struct HandlingError {
120 pub code: Option<ResponseType>,
121 pub message: String,
122}
123
124impl fmt::Display for HandlingError {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "Handling error {:?}: {}", self.code, self.message)
127 }
128}
129
130#[cfg(feature = "std")]
131impl error::Error for HandlingError {}
132
133impl HandlingError {
134 pub fn not_handled() -> Self {
135 Self {
136 code: None,
137 message: "Not handled".to_owned(),
138 }
139 }
140
141 pub fn not_found() -> Self {
142 Self::with_code(ResponseType::NotFound, "Not found")
143 }
144
145 pub fn bad_request<T: ToString>(e: T) -> Self {
146 Self::with_code(ResponseType::BadRequest, e)
147 }
148
149 pub fn internal<T: ToString>(e: T) -> Self {
150 Self::with_code(ResponseType::InternalServerError, e)
151 }
152
153 pub fn method_not_supported() -> Self {
154 Self::with_code(ResponseType::MethodNotAllowed, "Method not supported")
155 }
156
157 pub fn with_code<T: ToString>(code: ResponseType, e: T) -> Self {
158 Self {
159 code: Some(code),
160 message: e.to_string(),
161 }
162 }
163}