nd_util/
arc_anyhow_error.rs

1use std::fmt::Debug;
2use std::fmt::Display;
3use std::sync::Arc;
4
5/// An Arc'ed anyhow error.
6///
7/// It is not intended as a replacement for anyhow's error,
8/// just a way to share it as well as a way to provide an error impl.
9/// This means that this error can itself be placed into an anyhow::Error.
10///
11/// # Use Cases
12/// This error is intended to be used where multiple tasks want the result of a singular, shared operation.
13/// Consider a web request to a server to a static resource X.
14/// It is not desired behavior to send multiple parallel requests to resource X at once.
15/// Instead one would send 1 request and have all tasks that need it wait of the result.
16/// However, this means that both X and the error must be clonable.
17/// X can be make Clone with Arc<X>, and the error can be made clone with ArcAnyhowError.
18#[derive(Clone)]
19pub struct ArcAnyhowError(Arc<anyhow::Error>);
20
21impl ArcAnyhowError {
22    /// Make a new [`ArcAnyhowError`].
23    pub fn new(error: anyhow::Error) -> Self {
24        Self(Arc::new(error))
25    }
26}
27
28impl Debug for ArcAnyhowError {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        Debug::fmt(&*self.0, f)
31    }
32}
33
34impl Display for ArcAnyhowError {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        Display::fmt(&*self.0, f)
37    }
38}
39
40// We allow deprecated functions as this is just a wrapper,
41// we want to emulate anyhow::error's choices,
42// even if they use deprecated code
43impl std::error::Error for ArcAnyhowError {
44    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
45        self.0.as_ref().source()
46    }
47
48    #[allow(deprecated)]
49    fn description(&self) -> &str {
50        self.0.as_ref().description()
51    }
52
53    #[allow(deprecated)]
54    fn cause(&self) -> Option<&dyn std::error::Error> {
55        self.0.as_ref().cause()
56    }
57}