axum_error_sets/
api_error.rs1use crate::{IntoResponseWith, StatusWrapper};
2use axum_core::response::{IntoResponse, Response};
3use http::StatusCode;
4use std::{fmt::Debug, hash::Hash, marker::PhantomData};
5use type_sets::{Contains, SupersetOf};
6
7pub struct ErrorSet<T, E> {
16 value: T,
17 code: StatusCode,
18 _e: PhantomData<fn() -> E>,
19}
20
21impl<T, E> ErrorSet<T, E> {
22 pub fn new_with<R: StatusWrapper>(value: T) -> Self
26 where
27 E: Contains<R>,
28 {
29 Self::new_unchecked(value, R::STATUS_CODE)
30 }
31
32 pub fn new<R: StatusWrapper>(value: R) -> Self
37 where
38 E: Contains<R::Pure>,
39 R::Inner: Into<T>,
40 {
41 Self::new_with::<R::Pure>(value.into_inner().into())
42 }
43
44 pub fn new_unchecked(value: T, code: StatusCode) -> Self {
49 ErrorSet {
50 value,
51 code,
52 _e: PhantomData,
53 }
54 }
55
56 pub fn into_parts(self) -> (T, StatusCode) {
58 (self.value, self.code)
59 }
60
61 pub fn into_superset<E2>(self) -> ErrorSet<T, E2>
64 where
65 E2: SupersetOf<E>,
66 {
67 ErrorSet::new_unchecked(self.value, self.code)
68 }
69
70 pub fn map_value<F, U>(self, f: F) -> ErrorSet<U, E>
72 where
73 F: FnOnce(T) -> U,
74 {
75 ErrorSet::new_unchecked(f(self.value), self.code)
76 }
77
78 pub fn value(&self) -> &T {
80 &self.value
81 }
82
83 pub fn value_mut(&mut self) -> &mut T {
85 &mut self.value
86 }
87
88 pub fn status_code(&self) -> StatusCode {
90 self.code
91 }
92}
93
94impl<T: IntoResponseWith, R> IntoResponse for ErrorSet<T, R> {
95 fn into_response(self) -> Response {
96 self.value.into_response_with(self.code)
97 }
98}
99
100impl<T: Debug, R> Debug for ErrorSet<T, R> {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 f.debug_struct("ApiError")
103 .field("value", &self.value)
104 .field("code", &self.code)
105 .finish()
106 }
107}
108
109impl<T: Clone, R> Clone for ErrorSet<T, R> {
110 fn clone(&self) -> Self {
111 Self {
112 value: self.value.clone(),
113 code: self.code,
114 _e: PhantomData,
115 }
116 }
117}
118
119impl<T: Hash, R> Hash for ErrorSet<T, R> {
120 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
121 self.value.hash(state);
122 self.code.hash(state);
123 }
124}
125
126impl<T: PartialEq, R> PartialEq for ErrorSet<T, R> {
127 fn eq(&self, other: &Self) -> bool {
128 self.value == other.value && self.code == other.code
129 }
130}
131
132impl<T: Eq, R> Eq for ErrorSet<T, R> {}