@@ -71,45 +71,91 @@ impl From<ApiError> for PyErr {
7171 }
7272}
7373
74+ pub struct ResidualErrorData {
75+ message : String ,
76+ debug : String ,
77+ }
78+
7479#[ derive( Clone ) ]
75- pub struct SharedError {
76- pub err : Arc < anyhow:: Error > ,
80+ pub struct ResidualError ( Arc < ResidualErrorData > ) ;
81+
82+ impl Display for ResidualError {
83+ fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
84+ write ! ( f, "{}" , self . 0 . message)
85+ }
86+ }
87+
88+ impl Debug for ResidualError {
89+ fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
90+ write ! ( f, "{}" , self . 0 . debug)
91+ }
92+ }
93+
94+ impl Error for ResidualError { }
95+
96+ enum SharedErrorState {
97+ Anyhow ( anyhow:: Error ) ,
98+ ResidualErrorMessage ( ResidualError ) ,
7799}
78100
101+ /// SharedError allows to be cloned.
102+ /// The original `anyhow::Error` can be extracted once, and later it decays to `ResidualError` which preserves the message and debug information.
103+ #[ derive( Clone ) ]
104+ pub struct SharedError ( Arc < Mutex < SharedErrorState > > ) ;
105+
79106impl SharedError {
80107 pub fn new ( err : anyhow:: Error ) -> Self {
81- Self { err : Arc :: new ( err) }
108+ Self ( Arc :: new ( Mutex :: new ( SharedErrorState :: Anyhow ( err) ) ) )
109+ }
110+
111+ fn extract_anyhow_error ( & self ) -> anyhow:: Error {
112+ let mut state = self . 0 . lock ( ) . unwrap ( ) ;
113+ let mut_state = & mut * state;
114+
115+ let residual_err = match mut_state {
116+ SharedErrorState :: ResidualErrorMessage ( err) => {
117+ return anyhow:: Error :: from ( err. clone ( ) ) ;
118+ }
119+ SharedErrorState :: Anyhow ( err) => ResidualError ( Arc :: new ( ResidualErrorData {
120+ message : format ! ( "{}" , err) ,
121+ debug : format ! ( "{:?}" , err) ,
122+ } ) ) ,
123+ } ;
124+ let orig_state = std:: mem:: replace (
125+ mut_state,
126+ SharedErrorState :: ResidualErrorMessage ( residual_err) ,
127+ ) ;
128+ let SharedErrorState :: Anyhow ( err) = orig_state else {
129+ panic ! ( "Expected anyhow error" ) ;
130+ } ;
131+ err
82132 }
83133}
84134impl Debug for SharedError {
85135 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
86- Debug :: fmt ( & self . err , f)
136+ let state = self . 0 . lock ( ) . unwrap ( ) ;
137+ match & * state {
138+ SharedErrorState :: Anyhow ( err) => Debug :: fmt ( err, f) ,
139+ SharedErrorState :: ResidualErrorMessage ( err) => Debug :: fmt ( err, f) ,
140+ }
87141 }
88142}
89143
90144impl Display for SharedError {
91145 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
92- Display :: fmt ( & self . err , f)
146+ let state = self . 0 . lock ( ) . unwrap ( ) ;
147+ match & * state {
148+ SharedErrorState :: Anyhow ( err) => Display :: fmt ( err, f) ,
149+ SharedErrorState :: ResidualErrorMessage ( err) => Display :: fmt ( err, f) ,
150+ }
93151 }
94152}
95153
96154impl < E : std:: error:: Error + Send + Sync + ' static > From < E > for SharedError {
97155 fn from ( err : E ) -> Self {
98- Self {
99- err : Arc :: new ( anyhow:: Error :: from ( err) ) ,
100- }
101- }
102- }
103-
104- impl AsRef < dyn std:: error:: Error > for SharedError {
105- fn as_ref ( & self ) -> & ( dyn std:: error:: Error + ' static ) {
106- self . err . as_ref ( ) . as_ref ( )
107- }
108- }
109-
110- impl AsRef < dyn std:: error:: Error + Send + Sync > for SharedError {
111- fn as_ref ( & self ) -> & ( dyn std:: error:: Error + Send + Sync + ' static ) {
112- self . err . as_ref ( ) . as_ref ( )
156+ Self ( Arc :: new ( Mutex :: new ( SharedErrorState :: Anyhow (
157+ anyhow:: Error :: from ( err) ,
158+ ) ) ) )
113159 }
114160}
115161
@@ -119,48 +165,28 @@ pub fn shared_ok<T>(value: T) -> Result<T, SharedError> {
119165
120166pub type SharedResult < T > = Result < T , SharedError > ;
121167
122- pub struct SharedErrorWrapper ( SharedError ) ;
123-
124- impl Display for SharedErrorWrapper {
125- fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
126- Display :: fmt ( & self . 0 , f)
127- }
128- }
129-
130- impl Debug for SharedErrorWrapper {
131- fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
132- Debug :: fmt ( & self . 0 , f)
133- }
134- }
135-
136- impl Error for SharedErrorWrapper {
137- fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
138- self . 0 . err . as_ref ( ) . source ( )
139- }
140- }
141-
142168pub trait SharedResultExt < T > {
143- fn std_result ( self ) -> Result < T , SharedErrorWrapper > ;
169+ fn anyhow_result ( self ) -> Result < T , anyhow :: Error > ;
144170}
145171
146172impl < T > SharedResultExt < T > for Result < T , SharedError > {
147- fn std_result ( self ) -> Result < T , SharedErrorWrapper > {
173+ fn anyhow_result ( self ) -> Result < T , anyhow :: Error > {
148174 match self {
149175 Ok ( value) => Ok ( value) ,
150- Err ( err) => Err ( SharedErrorWrapper ( err) ) ,
176+ Err ( err) => Err ( err. extract_anyhow_error ( ) ) ,
151177 }
152178 }
153179}
154180
155181pub trait SharedResultExtRef < ' a , T > {
156- fn std_result ( self ) -> Result < & ' a T , SharedErrorWrapper > ;
182+ fn anyhow_result ( self ) -> Result < & ' a T , anyhow :: Error > ;
157183}
158184
159185impl < ' a , T > SharedResultExtRef < ' a , T > for & ' a Result < T , SharedError > {
160- fn std_result ( self ) -> Result < & ' a T , SharedErrorWrapper > {
186+ fn anyhow_result ( self ) -> Result < & ' a T , anyhow :: Error > {
161187 match self {
162188 Ok ( value) => Ok ( value) ,
163- Err ( err) => Err ( SharedErrorWrapper ( err. clone ( ) ) ) ,
189+ Err ( err) => Err ( err. extract_anyhow_error ( ) ) ,
164190 }
165191 }
166192}
0 commit comments