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        }))
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    // TODO(tailhook) use uuids of errors instead
91    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}