gel_errors/
traits.rs

1use std::borrow::Cow;
2use std::collections::HashMap;
3
4use crate::error::{Error, Inner, Source};
5
6/// Trait that marks Gel errors.
7///
8/// This is currently sealed because Gel errors will be changed in future.
9pub 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    // TODO(tailhook) use uuids of errors instead
95    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}