resplus_impl/
lib.rs

1#[cfg(feature = "async")]
2mod fut;
3#[cfg(feature = "async")]
4pub use fut::FutResultChain;
5mod sync;
6use std::{borrow::Cow, fmt::Display};
7pub use sync::ResultChain;
8
9#[derive(Debug)]
10struct Inner<I> {
11    pub source: I,
12    pub context: Vec<Cow<'static, str>>,
13}
14
15#[derive(Debug)]
16pub struct ErrorChain<I> {
17    inner: Box<Inner<I>>,
18}
19
20impl<I> ErrorChain<I> {
21    pub fn new(source: impl Into<I>) -> Self {
22        Self {
23            inner: Box::new(Inner {
24                source: source.into(),
25                context: Vec::new(),
26            }),
27        }
28    }
29    pub fn with_context(source: impl Into<I>, context: impl Into<Cow<'static, str>>) -> Self {
30        Self {
31            inner: Box::new(Inner {
32                source: source.into(),
33                context: vec![context.into()],
34            }),
35        }
36    }
37    pub fn append(&mut self, context: impl Into<Cow<'static, str>>) {
38        self.inner.context.push(context.into());
39    }
40    pub fn src(&self) -> &I {
41        &self.inner.source
42    }
43    pub fn ctx(&self) -> &[Cow<'static, str>] {
44        &self.inner.context
45    }
46}
47
48impl<I> std::error::Error for ErrorChain<I>
49where
50    I: std::error::Error + 'static,
51{
52    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
53        Some(&self.inner.source)
54    }
55}
56
57impl<I: Display> Display for ErrorChain<I> {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        write!(f, "source: {}", self.inner.source)?;
60        for c in self.ctx() {
61            write!(f, "\n  {}", c)?;
62        }
63        Ok(())
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    macro_rules! about {
70        ($e:expr) => {
71            ($e).about("source")
72        };
73    }
74    pub(crate) use about;
75    macro_rules! about_else {
76        ($e:expr) => {
77            ($e).about_else(|| "source")
78        };
79    }
80    pub(crate) use about_else;
81}