1pub mod config;
2pub mod cors;
3pub mod crypto;
4#[cfg(feature = "testing")]
5pub mod fee;
6pub mod formatting;
7pub mod grpc;
8pub mod limiter;
9pub mod logging;
10pub mod panic;
11pub mod tracing;
12pub mod version;
13
14pub trait ErrorReport: std::error::Error {
15 fn as_report(&self) -> String {
17 use std::fmt::Write;
18 let mut report = self.to_string();
19
20 std::iter::successors(self.source(), |child| child.source())
22 .for_each(|source| write!(report, "\ncaused by: {source}").unwrap());
23
24 report
25 }
26
27 fn as_report_context(&self, context: &'static str) -> String {
30 format!("{context}: \ncaused by: {}", self.as_report())
31 }
32}
33
34impl<T: std::error::Error> ErrorReport for T {}
35
36pub trait FlattenResult<V, OuterError, InnerError>
40where
41 InnerError: Into<OuterError>,
42{
43 fn flatten_result(self) -> Result<V, OuterError>;
44}
45
46impl<V, OuterError, InnerError> FlattenResult<V, OuterError, InnerError>
47 for Result<Result<V, InnerError>, OuterError>
48where
49 OuterError: From<InnerError>,
50{
51 fn flatten_result(self) -> Result<V, OuterError> {
52 match self {
53 Ok(Ok(value)) => Ok(value),
54 Ok(Err(inner)) => Err(inner.into()),
55 Err(outer) => Err(outer),
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::ErrorReport;
63
64 #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
65 pub enum TestSourceError {
66 #[error("source error")]
67 Source,
68 }
69
70 #[derive(thiserror::Error, Debug)]
71 pub enum TestError {
72 #[error("parent error")]
73 Parent(#[from] TestSourceError),
74 }
75
76 #[test]
77 fn as_report() {
78 let error = TestError::Parent(TestSourceError::Source);
79 assert_eq!("parent error\ncaused by: source error", error.as_report());
80 }
81
82 #[test]
83 fn as_report_context() {
84 let error = TestError::Parent(TestSourceError::Source);
85 assert_eq!(
86 "final error: \ncaused by: parent error\ncaused by: source error",
87 error.as_report_context("final error")
88 );
89 }
90}