Skip to main content

miden_node_utils/
lib.rs

1extern crate self as miden_node_utils;
2
3pub mod block_cache;
4pub mod clap;
5pub mod cors;
6#[cfg(feature = "testing")]
7pub mod fee;
8pub mod formatting;
9pub mod fs;
10pub mod genesis;
11pub mod grpc;
12pub mod limiter;
13pub mod logging;
14pub mod lru_cache;
15pub mod panic;
16pub mod retry;
17pub mod shutdown;
18pub mod spawn;
19pub mod tasks;
20pub mod tracing;
21
22pub trait ErrorReport: std::error::Error {
23    /// Returns a string representation of the error and its source chain.
24    fn as_report(&self) -> String {
25        use std::fmt::Write;
26        let mut report = self.to_string();
27
28        // SAFETY: write! is suggested by clippy, and is trivially safe usage.
29        std::iter::successors(self.source(), |child| child.source())
30            .for_each(|source| write!(report, "\ncaused by: {source}").unwrap());
31
32        report
33    }
34
35    /// Creates a new root in the error chain and returns a string representation of the error and
36    /// its source chain.
37    fn as_report_context(&self, context: &'static str) -> String {
38        format!("{context}: \ncaused by: {}", self.as_report())
39    }
40}
41
42impl<T: std::error::Error + ?Sized> ErrorReport for T {}
43
44/// Extends nested results types, allowing them to be flattened.
45///
46/// Adapted from: <https://stackoverflow.com/a/77543839>
47pub trait FlattenResult<V, OuterError, InnerError>
48where
49    InnerError: Into<OuterError>,
50{
51    fn flatten_result(self) -> Result<V, OuterError>;
52}
53
54impl<V, OuterError, InnerError> FlattenResult<V, OuterError, InnerError>
55    for Result<Result<V, InnerError>, OuterError>
56where
57    OuterError: From<InnerError>,
58{
59    fn flatten_result(self) -> Result<V, OuterError> {
60        match self {
61            Ok(Ok(value)) => Ok(value),
62            Ok(Err(inner)) => Err(inner.into()),
63            Err(outer) => Err(outer),
64        }
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use crate::ErrorReport;
71
72    #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
73    pub enum TestSourceError {
74        #[error("source error")]
75        Source,
76    }
77
78    #[derive(thiserror::Error, Debug)]
79    pub enum TestError {
80        #[error("parent error")]
81        Parent(#[from] TestSourceError),
82    }
83
84    #[test]
85    fn as_report() {
86        let error = TestError::Parent(TestSourceError::Source);
87        assert_eq!("parent error\ncaused by: source error", error.as_report());
88    }
89
90    #[test]
91    fn as_report_context() {
92        let error = TestError::Parent(TestSourceError::Source);
93        assert_eq!(
94            "final error: \ncaused by: parent error\ncaused by: source error",
95            error.as_report_context("final error")
96        );
97    }
98}