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 source(&self) -> &I {
41 &self.inner.source
42 }
43}
44
45impl<I: Display> Display for ErrorChain<I> {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "source: {}", self.inner.source)?;
48 for c in self.inner.context.iter() {
49 write!(f, "\n {}", c)?;
50 }
51 Ok(())
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 macro_rules! about {
58 ($e:expr) => {
59 ($e).about("source")
60 };
61 }
62 pub(crate) use about;
63 macro_rules! about_else {
64 ($e:expr) => {
65 ($e).about_else(|| "source")
66 };
67 }
68 pub(crate) use about_else;
69}