1macro_rules! impl_error {
2 ($ty:ident,$message:expr) => {
3 #[doc = concat!("The error type of `", stringify!($ty), "`.")]
4 #[derive(Debug)]
5 pub struct $ty {
6 _priv: (),
7 }
8
9 impl $ty {
10 pub(crate) fn new() -> Self {
11 Self { _priv: () }
12 }
13 }
14
15 impl core::fmt::Display for $ty {
16 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17 f.write_str($message)
18 }
19 }
20
21 impl core::error::Error for $ty {}
22 };
23}
24
25#[macro_export]
30macro_rules! http_error_fmt {
31 ($(#[$meta:meta])* $vis:vis $name:ident, $status:expr, |$ty_self:pat, $fmt:ident| $body:expr $(,)?) => {
32 $(#[$meta])*
33 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
34 $vis struct $name {
35 _priv: (),
36 }
37
38 impl $name {
39 pub const fn new() -> Self {
41 Self { _priv: () }
42 }
43 }
44
45 impl ::core::default::Default for $name {
46 fn default() -> Self {
47 Self::new()
48 }
49 }
50
51 impl ::core::fmt::Display for $name {
52 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
53 let $ty_self = self;
54 let $fmt = f;
55 $body
56 }
57 }
58
59 impl ::core::error::Error for $name {}
60
61 impl $crate::HttpError for $name {
62 fn status(&self) -> ::core::option::Option<$crate::StatusCode> {
63 ::core::option::Option::Some($status)
64 }
65 }
66 };
67}
68
69#[macro_export]
88macro_rules! http_error {
89 ($(#[$meta:meta])* $vis:vis $name:ident, $status:expr, $message:expr $(,)?) => {
90 $crate::http_error_fmt!(
91 $(#[$meta])*
92 $vis $name,
93 $status,
94 |_, f| { f.write_str($message) },
95 );
96 };
97}
98
99#[cfg(test)]
100mod tests {
101 use crate::{HttpError, StatusCode};
102 use alloc::string::ToString;
103
104 http_error!(
105 pub MacroNotFound,
107 StatusCode::NOT_FOUND,
108 "macro missing"
109 );
110
111 http_error_fmt!(
112 pub MacroDisplayError,
114 StatusCode::BAD_REQUEST,
115 |_, f| write!(f, "bad request (400)"),
116 );
117
118 #[test]
119 fn http_error_macros_create_expected_types() {
120 let not_found = MacroNotFound::new();
121 assert_eq!(not_found.status(), Some(StatusCode::NOT_FOUND));
122 assert_eq!(not_found.to_string(), "macro missing");
123
124 let display = MacroDisplayError::new();
125 assert_eq!(display.status(), Some(StatusCode::BAD_REQUEST));
126 assert_eq!(display.to_string(), "bad request (400)");
127 }
128}