1use std::borrow::Cow;
2use std::collections::HashMap;
3
4use crate::error::{Error, Inner, Source};
5
6pub trait ErrorKind: Sealed {
10 fn with_message<S: Into<Cow<'static, str>>>(s: S) -> Error {
11 Self::build().context(s)
12 }
13 fn with_source<E: std::error::Error + Send + Sync + 'static>(src: E) -> Error {
14 Error(Box::new(Inner {
15 code: Self::CODE,
16 messages: Vec::new(),
17 error: Some(Source::Box(src.into())),
18 headers: HashMap::new(),
19 fields: HashMap::new(),
20 }))
21 }
22 fn with_source_box(src: Box<dyn std::error::Error + Send + Sync>) -> Error {
23 Error(Box::new(Inner {
24 code: Self::CODE,
25 messages: Vec::new(),
26 error: Some(Source::Box(src)),
27 headers: HashMap::new(),
28 fields: HashMap::new(),
29 }))
30 }
31 fn with_source_ref<T>(src: T) -> Error
32 where
33 T: AsRef<dyn std::error::Error + Send + Sync>,
34 T: Send + Sync + 'static,
35 {
36 Error(Box::new(Inner {
37 code: Self::CODE,
38 messages: Vec::new(),
39 error: Some(Source::Ref(Box::new(src))),
40 headers: HashMap::new(),
41 fields: HashMap::new(),
42 }))
43 }
44 fn build() -> Error {
45 Error(Box::new(Inner {
46 code: Self::CODE,
47 messages: Vec::new(),
48 error: None,
49 headers: HashMap::new(),
50 fields: HashMap::new(),
51 }))
52 }
53}
54
55pub trait Field {
56 const NAME: &'static str;
57 type Value: Send + Sync + 'static;
58}
59
60pub trait ResultExt<T> {
61 fn context<C>(self, context: C) -> Result<T, Error>
62 where
63 C: Into<Cow<'static, str>>;
64 fn with_context<C, F>(self, f: F) -> Result<T, Error>
65 where
66 C: Into<Cow<'static, str>>,
67 F: FnOnce() -> C;
68}
69
70impl<T> ResultExt<T> for Result<T, Error> {
71 fn context<C>(self, context: C) -> Result<T, Error>
72 where
73 C: Into<Cow<'static, str>>,
74 {
75 self.map_err(|e| e.context(context))
76 }
77 fn with_context<C, F>(self, f: F) -> Result<T, Error>
78 where
79 C: Into<Cow<'static, str>>,
80 F: FnOnce() -> C,
81 {
82 self.map_err(|e| e.context(f()))
83 }
84}
85
86pub trait Sealed {
87 const CODE: u32;
88 const NAME: &'static str;
89 const TAGS: u32;
90 fn is_superclass_of(code: u32) -> bool {
92 let mask = 0xFFFFFFFF_u32 << ((Self::CODE.trailing_zeros() / 8) * 8);
93 code & mask == Self::CODE
94 }
95 fn has_tag(bit: u32) -> bool {
96 Self::TAGS & (1 << bit) != 0
97 }
98}