miden_node_utils/
lib.rs

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