another_rxrust/
rx_error.rs

1use std::{any::TypeId, sync::Arc};
2
3struct RxErrorInner {
4  error: Box<dyn std::any::Any + Send + Sync + 'static>,
5  get_str: Box<dyn Fn(&Self) -> String + Send + Sync>,
6}
7
8#[derive(Clone)]
9pub struct RxError {
10  inner: Arc<RxErrorInner>,
11}
12
13impl RxError {
14  pub fn from_error<E>(err: E) -> RxError
15  where
16    E: std::fmt::Debug + Send + Sync + 'static,
17  {
18    RxError {
19      inner: Arc::new(RxErrorInner {
20        error: Box::new(err),
21        get_str: Box::new(|x: &RxErrorInner| {
22          format!(
23            "RxError({}) -> {:?}",
24            std::any::type_name::<E>(),
25            x.error.downcast_ref::<E>().unwrap()
26          )
27        }),
28      }),
29    }
30  }
31
32  pub fn from_result<T, E>(result: Result<T, E>) -> RxError
33  where
34    T: std::fmt::Debug,
35    E: std::fmt::Debug + Send + Sync + 'static,
36  {
37    RxError {
38      inner: Arc::new(RxErrorInner {
39        error: Box::new(result.expect_err("Result must be Result::Err!")),
40        get_str: Box::new(|x: &RxErrorInner| {
41          format!(
42            "RxError({}) -> {:?}",
43            std::any::type_name::<E>(),
44            x.error.downcast_ref::<E>().unwrap()
45          )
46        }),
47      }),
48    }
49  }
50
51  pub fn downcast_ref<E>(&self) -> Option<&E>
52  where
53    E: Send + Sync + 'static,
54  {
55    self.inner.error.downcast_ref::<E>()
56  }
57
58  pub fn type_id(&self) -> TypeId {
59    self.inner.error.type_id()
60  }
61
62  pub fn is<T>(&self) -> bool
63  where
64    T: 'static,
65  {
66    self.inner.error.is::<T>()
67  }
68}
69
70impl std::fmt::Debug for RxError {
71  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72    f.pad(&self.to_string())
73  }
74}
75
76impl std::string::ToString for RxError {
77  fn to_string(&self) -> String {
78    (self.inner.get_str)(&self.inner)
79  }
80}
81
82#[cfg(test)]
83mod test {
84  use crate::prelude::*;
85  use anyhow::anyhow;
86
87  #[test]
88  fn str_ref() {
89    let error = Err::<i32, _>("aaa");
90
91    let e = RxError::from_error(error.expect_err("?"));
92    println!("{:?}", e.downcast_ref::<&str>());
93
94    let e = RxError::from_result(error);
95    println!("{:?}", e.downcast_ref::<&str>());
96    println!("{:?}", e);
97  }
98
99  #[test]
100  fn from_error() {
101    let error = Err::<i32, _>(std::io::Error::from(
102      std::io::ErrorKind::NotFound,
103    ));
104    let e = RxError::from_error(error.expect_err("?"));
105    println!(
106      "{:?}",
107      e.downcast_ref::<std::io::Error>()
108    );
109
110    let error = Err::<i32, _>(std::io::Error::from(
111      std::io::ErrorKind::NotFound,
112    ));
113    let e = RxError::from_result(error);
114    println!(
115      "{:?}",
116      e.downcast_ref::<std::io::Error>()
117    );
118    println!("{:?}", e);
119  }
120
121  #[test]
122  fn anyhow_error() {
123    let error = Err::<i32, _>(anyhow!("anyhow error"));
124    let e = RxError::from_result(error);
125    println!(
126      "{:?}",
127      e.downcast_ref::<anyhow::Error>()
128    );
129    println!("{:?}", e);
130  }
131}