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}