another_rxrust/
rx_error.rs1use 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}