1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/// A macro to attach status codes to enum errors.
/// ```
/// use http::StatusCode;
///
/// #[status_code]
/// pub enum DatabaseError {
/// #[code(StatusCode::NOT_FOUND)]
/// NotFoundInDatabase,
/// #[code(StatusCode::INTERNAL_SERVER_ERROR)]
/// DatabaseNetworkError
/// }
/// ```
///
/// You can also set a default and override when neccesary.
/// ```
/// use http::StatusCode;
///
/// #[status_code(StatusCode::FORBIDDEN)]
/// pub enum TokenError {
/// MalformedToken,
/// InvalidToken,
/// #[code(StatusCode::INTERNAL_SERVER_ERROR)]
/// DeserializationError
/// }
/// ```
///
/// You can even include the contents of the enum!
/// ```
/// use http::StatusCode;
///
/// #[status_code]
/// pub enum Error {
/// #[pattern((code, _, _))]
/// // Note that you have to deference as we borrow the enum
/// #[code(*code)]
/// Dynamic(StatusCode, (), ()),
/// #[pattern({ status, .. })]
/// #[code(*status)]
/// DynamicStruct {
/// status: StatusCode,
/// ctx: (),
/// }
/// }
/// ```
///
/// You can even write arbitrary code!
/// ```
/// #[status_code]
/// pub enum Error {
/// #[pattern((ctx))]
/// #[code({
/// let result = StatusCode::try_from(ctx.status_code()).unwrap();
/// return result
/// })]
/// Number(ErrorContext)
/// }
/// ```
///
/// The interior of the code attribute, as you've probably figured out, is the contents of the match arm (which is what the macro expands to).
/// The interior of the pattern attribute is the binding pattern to which to bind variables to. Note that the name of the variant should not be included here.
///
/// ```
/// match enum {
/// Variant #pattern => #attribute,
/// ...
/// }
/// ```
///
/// Pattern is optional, being filled in by an ignore-all if not set.
/// Code is only optional if a default status code is set in the top-level status_code attribute.
///
/// Find out what status code something has using the as_status_code function.
/// ```
/// pub fn endpoint(...) -> impl IntoResponse {
/// let user = fetch_user(cookies);
/// if let Err(err) = user {
/// return (err.as_status_code(), err.to_string())
/// }
/// }
/// ```
pub use status_code;
pub use http;