1use std::error::Error;
11use std::sync::Arc;
12
13use thiserror::Error;
14
15#[derive(Error, Debug)]
51#[error(transparent)]
52pub struct SharedError<T: Error + 'static> {
53 #[from]
54 error: Arc<T>,
55}
56
57impl<T: Error + 'static> Clone for SharedError<T> {
58 fn clone(&self) -> Self {
59 Self {
60 error: self.error.clone(),
61 }
62 }
63}
64
65impl<T: Error + 'static> From<T> for SharedError<T> {
66 fn from(error: T) -> SharedError<T> {
67 SharedError {
68 error: Arc::new(error),
69 }
70 }
71}
72
73impl<T: Error + 'static> SharedError<T> {
74 pub fn inner(&self) -> &T {
76 &self.error
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use thiserror::Error;
83
84 use super::*;
85
86 #[derive(Debug, Error)]
87 enum TestError {
88 #[error("Some error: {0}")]
89 SomeError(String),
90 }
91
92 #[test]
93 fn test_convert_to_shared_error() {
94 let error = TestError::SomeError("some context".to_owned());
95 let shared_error: SharedError<_> = error.into();
96 assert_eq!(
97 shared_error.inner().to_string(),
98 "Some error: some context".to_owned()
99 );
100 assert_eq!(
101 shared_error.to_string(),
102 "Some error: some context".to_owned()
103 );
104 assert!(shared_error.source().is_none());
105 }
106
107 #[test]
108 #[allow(clippy::redundant_clone)]
109 fn test_clone_shared_error() {
110 let error = TestError::SomeError("some context".to_owned());
111 let shared_error: SharedError<_> = error.into();
112 let cloned_error = shared_error.clone();
113 assert_eq!(
114 cloned_error.inner().to_string(),
115 "Some error: some context".to_owned()
116 );
117 assert_eq!(
118 cloned_error.to_string(),
119 "Some error: some context".to_owned()
120 );
121 assert!(shared_error.source().is_none());
122 }
123
124 #[test]
125 fn test_convert_to_result_with_shared_error() {
126 fn some_fallible_func() -> Result<(), SharedError<TestError>> {
127 let result: Result<(), TestError> =
128 Err(TestError::SomeError("some context".to_owned()));
129 Ok(result?)
130 }
131
132 let shared_error_result = some_fallible_func();
133 match shared_error_result {
134 Ok(_) => panic!("Can't be an Ok result"),
135 Err(shared_error) => {
136 assert_eq!(
137 shared_error.to_string(),
138 "Some error: some context".to_owned()
139 );
140 assert!(shared_error.source().is_none());
141 }
142 }
143 }
144}