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