valico/common/
error.rs

1use std::error::Error;
2use std::fmt::Debug;
3
4use downcast_rs::Downcast;
5
6pub trait ValicoError: Downcast + Error + Send + Debug + erased_serde::Serialize {
7    fn get_code(&self) -> &str;
8    fn get_path(&self) -> &str;
9    fn get_title(&self) -> &str;
10    fn get_detail(&self) -> Option<&str> {
11        None
12    }
13}
14
15erased_serde::serialize_trait_object!(ValicoError);
16downcast_rs::impl_downcast!(ValicoError);
17
18pub type ValicoErrors = Vec<Box<dyn ValicoError>>;
19
20macro_rules! impl_basic_err {
21    ($err:ty, $code:expr) => {
22        impl ::std::error::Error for $err {}
23
24        impl ::std::fmt::Display for $err {
25            fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
26                write!(formatter, $code)
27            }
28        }
29    };
30}
31
32macro_rules! impl_err {
33    ($err:ty, $code:expr, $title:expr) => {
34        impl_basic_err!($err, $code);
35
36        impl $crate::common::error::ValicoError for $err {
37            fn get_code(&self) -> &str {
38                $code
39            }
40            fn get_title(&self) -> &str {
41                $title
42            }
43            fn get_path(&self) -> &str {
44                self.path.as_ref()
45            }
46        }
47    };
48
49    ($err:ty, $code:expr, $title:expr, +detail) => {
50        impl_basic_err!($err, $code);
51
52        impl $crate::common::error::ValicoError for $err {
53            fn get_code(&self) -> &str {
54                $code
55            }
56            fn get_title(&self) -> &str {
57                $title
58            }
59            fn get_path(&self) -> &str {
60                self.path.as_ref()
61            }
62            fn get_detail(&self) -> Option<&str> {
63                Some(self.detail.as_ref())
64            }
65        }
66    };
67
68    ($err:ty, $code:expr, $title:expr, +opt_detail) => {
69        impl_basic_err!($err, $code);
70
71        impl $crate::common::error::ValicoError for $err {
72            fn get_code(&self) -> &str {
73                $code
74            }
75            fn get_title(&self) -> &str {
76                $title
77            }
78            fn get_path(&self) -> &str {
79                self.path.as_ref()
80            }
81            fn get_detail(&self) -> Option<&str> {
82                self.detail.as_ref().map(|s| s.as_ref())
83            }
84        }
85    };
86}
87
88macro_rules! impl_serialize {
89    ($err:ty) => {
90        impl Serialize for $err {
91            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
92                let mut map = ::serde_json::Map::new();
93                map.insert("code".to_string(), to_value(self.get_code()).unwrap());
94                map.insert("title".to_string(), to_value(self.get_title()).unwrap());
95                map.insert("path".to_string(), to_value(self.get_path()).unwrap());
96                if let Some(ref detail) = self.get_detail() {
97                    map.insert("detail".to_string(), to_value(detail).unwrap());
98                }
99                Value::Object(map).serialize(serializer)
100            }
101        }
102    };
103    ($err:ty, $($sp:expr),+) => {
104        impl Serialize for $err {
105            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
106                let mut map = ::serde_json::Map::new();
107                map.insert("code".to_string(), to_value(self.get_code()).unwrap());
108                map.insert("title".to_string(), to_value(self.get_title()).unwrap());
109                map.insert("path".to_string(), to_value(self.get_path()).unwrap());
110                if let Some(ref detail) = self.get_detail() {
111                    map.insert("detail".to_string(), to_value(detail).unwrap());
112                }
113                $({
114                    let closure = $sp;
115                    closure(self, &mut map);
116                })+
117                Value::Object(map).serialize(serializer)
118            }
119        }
120    }
121}