1use super::Error;
12use bondrewd::Bitfields;
13
14#[derive(Bitfields, Debug, PartialEq, Eq, Copy, Clone)]
16#[bondrewd(default_endianness = "big", enforce_bytes = 1)]
17pub(crate) struct EncodedCode {
18 #[bondrewd(bit_length = 3)]
19 pub(crate) class: u8,
20 #[bondrewd(bit_length = 5)]
21 pub(crate) detail: u8,
22}
23
24impl From<Code> for EncodedCode {
25 fn from(code: Code) -> EncodedCode {
26 let (class, detail) = match code {
27 Code::Empty => (0, 0),
28 Code::Request(code) => match code {
29 RequestCode::Get => (0, 1),
30 RequestCode::Post => (0, 2),
31 RequestCode::Put => (0, 3),
32 RequestCode::Delete => (0, 4),
33 },
34 Code::Response(code) => match code {
35 ResponseCode::Success(code) => match code {
36 SuccessCode::Created => (2, 1),
37 SuccessCode::Deleted => (2, 2),
38 SuccessCode::Valid => (2, 3),
39 SuccessCode::Changed => (2, 4),
40 SuccessCode::Content => (2, 5),
41 },
42 ResponseCode::ClientError(code) => match code {
43 ClientErrorCode::BadRequest => (4, 0),
44 ClientErrorCode::Unauthorized => (4, 1),
45 ClientErrorCode::BadOption => (4, 2),
46 ClientErrorCode::Forbidden => (4, 3),
47 ClientErrorCode::NotFound => (4, 4),
48 ClientErrorCode::MethodNotAllowed => (4, 5),
49 ClientErrorCode::NotAcceptable => (4, 6),
50 ClientErrorCode::PreconditionFailed => (4, 12),
51 ClientErrorCode::RequestEntityTooLarge => (4, 13),
52 ClientErrorCode::UnsupportedContentFormat => (4, 15),
53 },
54 ResponseCode::ServerError(code) => match code {
55 ServerErrorCode::InternalServerError => (5, 0),
56 ServerErrorCode::NotImplemented => (5, 1),
57 ServerErrorCode::BadGateway => (5, 2),
58 ServerErrorCode::ServiceUnavailable => (5, 3),
59 ServerErrorCode::GatewayTimeout => (5, 4),
60 ServerErrorCode::ProxyingNotSupported => (5, 5),
61 },
62 },
63 };
64
65 EncodedCode { class, detail }
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum Code {
72 Empty,
74 Request(RequestCode),
76 Response(ResponseCode),
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum RequestCode {
83 Get,
85 Post,
87 Put,
89 Delete,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95pub enum ResponseCode {
96 Success(SuccessCode),
98 ClientError(ClientErrorCode),
100 ServerError(ServerErrorCode),
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
106pub enum SuccessCode {
107 Created,
109 Deleted,
111 Valid,
113 Changed,
115 Content,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum ClientErrorCode {
122 BadRequest,
124 Unauthorized,
126 BadOption,
128 Forbidden,
130 NotFound,
132 MethodNotAllowed,
134 NotAcceptable,
136 PreconditionFailed,
138 RequestEntityTooLarge,
140 UnsupportedContentFormat,
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub enum ServerErrorCode {
147 InternalServerError,
149 NotImplemented,
151 BadGateway,
153 ServiceUnavailable,
155 GatewayTimeout,
157 ProxyingNotSupported,
159}
160
161impl From<RequestCode> for Code {
162 fn from(code: RequestCode) -> Code {
163 Code::Request(code)
164 }
165}
166
167impl TryFrom<Code> for RequestCode {
168 type Error = ();
169
170 fn try_from(value: Code) -> Result<Self, Self::Error> {
171 match value {
172 Code::Request(code) => Ok(code),
173 _ => Err(()),
174 }
175 }
176}
177
178impl From<ResponseCode> for Code {
179 fn from(code: ResponseCode) -> Code {
180 Code::Response(code)
181 }
182}
183
184impl TryFrom<Code> for ResponseCode {
185 type Error = ();
186
187 fn try_from(value: Code) -> Result<Self, Self::Error> {
188 match value {
189 Code::Response(code) => Ok(code),
190 _ => Err(()),
191 }
192 }
193}
194
195impl From<SuccessCode> for ResponseCode {
196 fn from(code: SuccessCode) -> ResponseCode {
197 ResponseCode::Success(code)
198 }
199}
200
201impl From<SuccessCode> for Code {
202 fn from(code: SuccessCode) -> Code {
203 ResponseCode::Success(code).into()
204 }
205}
206
207impl TryFrom<Code> for SuccessCode {
208 type Error = ();
209
210 fn try_from(value: Code) -> Result<Self, Self::Error> {
211 match value {
212 Code::Response(ResponseCode::Success(code)) => Ok(code),
213 _ => Err(()),
214 }
215 }
216}
217
218impl From<ClientErrorCode> for ResponseCode {
219 fn from(code: ClientErrorCode) -> ResponseCode {
220 ResponseCode::ClientError(code)
221 }
222}
223
224impl From<ClientErrorCode> for Code {
225 fn from(code: ClientErrorCode) -> Code {
226 ResponseCode::ClientError(code).into()
227 }
228}
229
230impl TryFrom<Code> for ClientErrorCode {
231 type Error = ();
232
233 fn try_from(value: Code) -> Result<Self, Self::Error> {
234 match value {
235 Code::Response(ResponseCode::ClientError(code)) => Ok(code),
236 _ => Err(()),
237 }
238 }
239}
240
241impl From<ServerErrorCode> for ResponseCode {
242 fn from(code: ServerErrorCode) -> ResponseCode {
243 ResponseCode::ServerError(code)
244 }
245}
246
247impl From<ServerErrorCode> for Code {
248 fn from(code: ServerErrorCode) -> Code {
249 ResponseCode::ServerError(code).into()
250 }
251}
252
253impl TryFrom<Code> for ServerErrorCode {
254 type Error = ();
255
256 fn try_from(value: Code) -> Result<Self, Self::Error> {
257 match value {
258 Code::Response(ResponseCode::ServerError(code)) => Ok(code),
259 _ => Err(()),
260 }
261 }
262}
263
264impl TryFrom<EncodedCode> for Code {
265 type Error = Error;
266
267 fn try_from(code: EncodedCode) -> Result<Code, Self::Error> {
268 let code = match (code.class, code.detail) {
269 (0, 0) => Code::Empty,
271 (0, 1) => RequestCode::Get.into(),
273 (0, 2) => RequestCode::Post.into(),
274 (0, 3) => RequestCode::Put.into(),
275 (0, 4) => RequestCode::Delete.into(),
276 (2, 1) => SuccessCode::Created.into(),
278 (2, 2) => SuccessCode::Deleted.into(),
279 (2, 3) => SuccessCode::Valid.into(),
280 (2, 4) => SuccessCode::Changed.into(),
281 (2, 5) => SuccessCode::Content.into(),
282 (4, 0) => ClientErrorCode::BadRequest.into(),
284 (4, 1) => ClientErrorCode::Unauthorized.into(),
285 (4, 2) => ClientErrorCode::BadOption.into(),
286 (4, 3) => ClientErrorCode::Forbidden.into(),
287 (4, 4) => ClientErrorCode::NotFound.into(),
288 (4, 5) => ClientErrorCode::MethodNotAllowed.into(),
289 (4, 6) => ClientErrorCode::NotAcceptable.into(),
290 (4, 12) => ClientErrorCode::PreconditionFailed.into(),
291 (4, 13) => ClientErrorCode::RequestEntityTooLarge.into(),
292 (4, 15) => ClientErrorCode::UnsupportedContentFormat.into(),
293 (5, 0) => ServerErrorCode::InternalServerError.into(),
295 (5, 1) => ServerErrorCode::NotImplemented.into(),
296 (5, 2) => ServerErrorCode::BadGateway.into(),
297 (5, 3) => ServerErrorCode::ServiceUnavailable.into(),
298 (5, 4) => ServerErrorCode::GatewayTimeout.into(),
299 (5, 5) => ServerErrorCode::ProxyingNotSupported.into(),
300 (_, _) => return Err(Error::InvalidCode),
302 };
303
304 Ok(code)
305 }
306}