Skip to main content

other_error/
rc.rs

1use core::ops::Deref;
2use alloc::rc::Rc;
3
4/// Reference-counted error for sharing within a single thread.
5pub struct RcError<E> {
6    inner_error: Rc<E>,
7}
8
9impl<E> Clone for RcError<E> {
10    fn clone(&self) -> Self {
11        Self {
12            inner_error: self.inner_error.clone(),
13        }
14    }
15}
16
17impl<E> Deref for RcError<E> {
18    type Target = E;
19    fn deref(&self) -> &E {
20        &self.inner_error
21    }
22}
23
24impl<E: PartialEq> PartialEq for RcError<E> {
25    fn eq(&self, other: &Self) -> bool {
26        self.inner_error == other.inner_error
27    }
28}
29
30impl<E: Eq> Eq for RcError<E> {}
31
32impl<E> AsRef<E> for RcError<E> {
33    fn as_ref(&self) -> &E {
34        &self.inner_error
35    }
36}
37
38impl<E> From<E> for RcError<E> {
39    fn from(inner_error: E) -> Self {
40        Self::new(inner_error)
41    }
42}
43
44impl<E> RcError<E> {
45    pub fn new(inner_error: E) -> Self {
46        Self {
47            inner_error: Rc::new(inner_error),
48        }
49    }
50}
51
52impl<E: core::fmt::Debug> core::fmt::Debug for RcError<E> {
53    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54        core::fmt::Debug::fmt(&self.inner_error, f)
55    }
56}
57
58impl<E: core::fmt::Display> core::fmt::Display for RcError<E> {
59    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60        core::fmt::Display::fmt(&self.inner_error, f)
61    }
62}
63
64impl<E: core::error::Error> core::error::Error for RcError<E> {
65    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
66        self.inner_error.source()
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use alloc::format;
74
75    #[derive(Debug)]
76    struct MyError;
77
78    impl core::fmt::Display for MyError {
79        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80            f.write_str("my error")
81        }
82    }
83
84    #[test]
85    fn new_and_deref() {
86        let err = RcError::new(MyError);
87        assert_eq!(format!("{}", *err), "my error");
88    }
89
90    #[test]
91    fn from_and_display() {
92        let err: RcError<MyError> = MyError.into();
93        assert_eq!(format!("{}", err), "my error");
94        assert_eq!(format!("{:?}", err), "MyError");
95    }
96
97    #[test]
98    fn clone_shares_allocation() {
99        let err = RcError::new(MyError);
100        let cloned = err.clone();
101        assert!(Rc::ptr_eq(&err.inner_error, &cloned.inner_error));
102    }
103}