@@ -10,7 +10,11 @@ use std::fmt;
10
10
11
11
use godot_ffi:: VariantType ;
12
12
13
- use crate :: builtin:: { array_inner, meta:: ClassName } ;
13
+ use crate :: builtin:: {
14
+ array_inner,
15
+ meta:: { ClassName , ToGodot } ,
16
+ Variant ,
17
+ } ;
14
18
15
19
type Cause = Box < dyn Error + Send + Sync > ;
16
20
@@ -20,8 +24,7 @@ type Cause = Box<dyn Error + Send + Sync>;
20
24
#[ derive( Debug ) ]
21
25
pub struct ConvertError {
22
26
kind : ErrorKind ,
23
- cause : Option < Cause > ,
24
- value_str : Option < String > ,
27
+ value : Option < Variant > ,
25
28
}
26
29
27
30
impl ConvertError {
@@ -30,77 +33,71 @@ impl ConvertError {
30
33
/// If you don't need a custom message, consider using [`ConvertError::default()`] instead.
31
34
pub fn new ( user_message : impl Into < String > ) -> Self {
32
35
Self {
33
- kind : ErrorKind :: Custom ( Some ( user_message. into ( ) ) ) ,
34
- cause : None ,
35
- value_str : None ,
36
+ kind : ErrorKind :: Custom ( Some ( user_message. into ( ) . into ( ) ) ) ,
37
+ ..Default :: default ( )
36
38
}
37
39
}
38
40
39
41
/// Create a new custom error for a conversion with the value that failed to convert.
40
42
pub ( crate ) fn with_kind_value < V > ( kind : ErrorKind , value : V ) -> Self
41
43
where
42
- V : fmt :: Debug ,
44
+ V : ToGodot ,
43
45
{
44
46
Self {
45
47
kind,
46
- cause : None ,
47
- value_str : Some ( format ! ( "{value:?}" ) ) ,
48
+ value : Some ( value. to_variant ( ) ) ,
48
49
}
49
50
}
50
51
51
- /// Create a new custom error with a rust-error as an underlying cause for the conversion error.
52
- #[ doc( hidden) ]
53
- pub fn with_cause < C > ( cause : C ) -> Self
52
+ /// Create a new custom error wrapping an [`Error`].
53
+ pub fn with_error < E > ( error : E ) -> Self
54
54
where
55
- C : Into < Cause > ,
55
+ E : Into < Box < dyn Error + Send + Sync > > ,
56
56
{
57
57
Self {
58
- cause : Some ( cause . into ( ) ) ,
58
+ kind : ErrorKind :: Custom ( Some ( error . into ( ) ) ) ,
59
59
..Default :: default ( )
60
60
}
61
61
}
62
62
63
- /// Create a new custom error with a rust-error as an underlying cause for the conversion error, and the
64
- /// value that failed to convert.
65
- #[ doc( hidden) ]
66
- pub fn with_cause_value < C , V > ( cause : C , value : V ) -> Self
63
+ /// Create a new custom error wrapping an [`Error`] and the value that failed to convert.
64
+ pub fn with_error_value < E , V > ( error : E , value : V ) -> Self
67
65
where
68
- C : Into < Cause > ,
69
- V : fmt :: Debug ,
66
+ E : Into < Box < dyn Error + Send + Sync > > ,
67
+ V : ToGodot ,
70
68
{
71
69
Self {
72
- cause : Some ( cause. into ( ) ) ,
73
- value_str : Some ( format ! ( "{value:?}" ) ) ,
74
- ..Default :: default ( )
70
+ kind : ErrorKind :: Custom ( Some ( error. into ( ) ) ) ,
71
+ value : Some ( value. to_variant ( ) ) ,
75
72
}
76
73
}
77
74
78
75
/// Returns the rust-error that caused this error, if one exists.
79
- pub fn cause ( & self ) -> Option < & ( dyn Error + Send + Sync ) > {
80
- self . cause . as_deref ( )
76
+ pub fn cause ( & self ) -> Option < & ( dyn Error + Send + Sync + ' static ) > {
77
+ match & self . kind {
78
+ ErrorKind :: Custom ( Some ( cause) ) => Some ( & * * cause) ,
79
+ _ => None ,
80
+ }
81
81
}
82
82
83
- /// Returns a string representation of the value that failed to convert, if one exists.
84
- pub fn value_str ( & self ) -> Option < & str > {
85
- self . value_str . as_deref ( )
83
+ /// Returns a reference of the value that failed to convert, if one exists.
84
+ pub fn value ( & self ) -> Option < & Variant > {
85
+ self . value . as_ref ( )
86
86
}
87
87
88
- fn description ( & self ) -> Option < String > {
89
- self . kind . description ( )
88
+ /// Converts error into generic error type. It is useful to send error across thread.
89
+ /// Do note that some data might get lost during conversion.
90
+ pub fn into_erased ( self ) -> impl Error + Send + Sync {
91
+ ErasedConvertError :: from ( self )
90
92
}
91
93
}
92
94
93
95
impl fmt:: Display for ConvertError {
94
96
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
95
- match ( self . description ( ) , self . cause . as_ref ( ) ) {
96
- ( Some ( desc) , Some ( cause) ) => write ! ( f, "{desc}: {cause}" ) ?,
97
- ( Some ( desc) , None ) => write ! ( f, "{desc}" ) ?,
98
- ( None , Some ( cause) ) => write ! ( f, "{cause}" ) ?,
99
- ( None , None ) => write ! ( f, "unknown error: {:?}" , self . kind) ?,
100
- }
97
+ write ! ( f, "{}" , self . kind) ?;
101
98
102
- if let Some ( value) = self . value_str . as_ref ( ) {
103
- write ! ( f, ": {value}" ) ?;
99
+ if let Some ( value) = & self . value {
100
+ write ! ( f, ": {value:? }" ) ?;
104
101
}
105
102
106
103
Ok ( ( ) )
@@ -109,9 +106,7 @@ impl fmt::Display for ConvertError {
109
106
110
107
impl Error for ConvertError {
111
108
fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
112
- self . cause
113
- . as_ref ( )
114
- . map ( |cause| & * * cause as & ( dyn Error + ' static ) )
109
+ self . cause ( ) . map ( |v| v as & ( dyn Error + ' static ) )
115
110
}
116
111
}
117
112
@@ -122,27 +117,54 @@ impl Default for ConvertError {
122
117
fn default ( ) -> Self {
123
118
Self {
124
119
kind : ErrorKind :: Custom ( None ) ,
125
- cause : None ,
126
- value_str : None ,
120
+ value : None ,
127
121
}
128
122
}
129
123
}
130
124
131
- #[ derive( Eq , PartialEq , Debug ) ]
125
+ /// Erased type of [`ConvertError`].
126
+ #[ derive( Debug ) ]
127
+ pub ( crate ) struct ErasedConvertError {
128
+ kind : ErrorKind ,
129
+ }
130
+
131
+ impl From < ConvertError > for ErasedConvertError {
132
+ fn from ( v : ConvertError ) -> Self {
133
+ let ConvertError { kind, .. } = v;
134
+ Self { kind }
135
+ }
136
+ }
137
+
138
+ impl fmt:: Display for ErasedConvertError {
139
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
140
+ write ! ( f, "{}" , self . kind)
141
+ }
142
+ }
143
+
144
+ impl Error for ErasedConvertError {
145
+ fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
146
+ match & self . kind {
147
+ ErrorKind :: Custom ( Some ( cause) ) => Some ( & * * cause) ,
148
+ _ => None ,
149
+ }
150
+ }
151
+ }
152
+
153
+ #[ derive( Debug ) ]
132
154
pub ( crate ) enum ErrorKind {
133
155
FromGodot ( FromGodotError ) ,
134
156
FromFfi ( FromFfiError ) ,
135
157
FromVariant ( FromVariantError ) ,
136
- Custom ( Option < String > ) ,
158
+ Custom ( Option < Cause > ) ,
137
159
}
138
160
139
- impl ErrorKind {
140
- fn description ( & self ) -> Option < String > {
161
+ impl fmt :: Display for ErrorKind {
162
+ fn fmt ( & self , f : & mut fmt :: Formatter < ' _ > ) -> fmt :: Result {
141
163
match self {
142
- Self :: FromGodot ( from_godot) => Some ( from_godot. description ( ) ) ,
143
- Self :: FromVariant ( from_variant) => Some ( from_variant. description ( ) ) ,
144
- Self :: FromFfi ( from_ffi) => Some ( from_ffi. description ( ) ) ,
145
- Self :: Custom ( description ) => description . clone ( ) ,
164
+ Self :: FromGodot ( from_godot) => write ! ( f , "{ from_godot}" ) ,
165
+ Self :: FromVariant ( from_variant) => write ! ( f , "{ from_variant}" ) ,
166
+ Self :: FromFfi ( from_ffi) => write ! ( f , "{ from_ffi}" ) ,
167
+ Self :: Custom ( cause ) => write ! ( f , "{cause:?}" ) ,
146
168
}
147
169
}
148
170
}
@@ -162,23 +184,27 @@ pub(crate) enum FromGodotError {
162
184
impl FromGodotError {
163
185
pub fn into_error < V > ( self , value : V ) -> ConvertError
164
186
where
165
- V : fmt :: Debug ,
187
+ V : ToGodot ,
166
188
{
167
189
ConvertError :: with_kind_value ( ErrorKind :: FromGodot ( self ) , value)
168
190
}
191
+ }
169
192
170
- fn description ( & self ) -> String {
193
+ impl fmt:: Display for FromGodotError {
194
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
171
195
match self {
172
196
Self :: BadArrayType { expected, actual } => {
173
197
if expected. variant_type ( ) != actual. variant_type ( ) {
174
198
return if expected. is_typed ( ) {
175
- format ! (
199
+ write ! (
200
+ f,
176
201
"expected array of type {:?}, got array of type {:?}" ,
177
202
expected. variant_type( ) ,
178
203
actual. variant_type( )
179
204
)
180
205
} else {
181
- format ! (
206
+ write ! (
207
+ f,
182
208
"expected untyped array, got array of type {:?}" ,
183
209
actual. variant_type( )
184
210
)
@@ -191,14 +217,15 @@ impl FromGodotError {
191
217
"BadArrayType with expected == got, this is a gdext bug"
192
218
) ;
193
219
194
- format ! (
220
+ write ! (
221
+ f,
195
222
"expected array of class {}, got array of class {}" ,
196
223
expected. class_name( ) ,
197
224
actual. class_name( )
198
225
)
199
226
}
200
- Self :: InvalidEnum => "invalid engine enum value" . into ( ) ,
201
- Self :: ZeroInstanceId => "`InstanceId` cannot be 0" . into ( ) ,
227
+ Self :: InvalidEnum => write ! ( f , "invalid engine enum value" ) ,
228
+ Self :: ZeroInstanceId => write ! ( f , "`InstanceId` cannot be 0" ) ,
202
229
}
203
230
}
204
231
}
@@ -220,15 +247,19 @@ pub(crate) enum FromFfiError {
220
247
impl FromFfiError {
221
248
pub fn into_error < V > ( self , value : V ) -> ConvertError
222
249
where
223
- V : fmt :: Debug ,
250
+ V : ToGodot ,
224
251
{
225
252
ConvertError :: with_kind_value ( ErrorKind :: FromFfi ( self ) , value)
226
253
}
254
+ }
227
255
228
- fn description ( & self ) -> String {
256
+ impl fmt:: Display for FromFfiError {
257
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
229
258
let target = match self {
230
- Self :: NullRawGd => return "`Gd` cannot be null" . into ( ) ,
231
- Self :: WrongObjectType => return "given object cannot be cast to target type" . into ( ) ,
259
+ Self :: NullRawGd => return write ! ( f, "`Gd` cannot be null" ) ,
260
+ Self :: WrongObjectType => {
261
+ return write ! ( f, "given object cannot be cast to target type" )
262
+ }
232
263
Self :: I32 => "i32" ,
233
264
Self :: I16 => "i16" ,
234
265
Self :: I8 => "i8" ,
@@ -237,7 +268,7 @@ impl FromFfiError {
237
268
Self :: U8 => "u8" ,
238
269
} ;
239
270
240
- format ! ( "`{target}` cannot store the given value" )
271
+ write ! ( f , "`{target}` cannot store the given value" )
241
272
}
242
273
}
243
274
@@ -257,25 +288,27 @@ pub(crate) enum FromVariantError {
257
288
impl FromVariantError {
258
289
pub fn into_error < V > ( self , value : V ) -> ConvertError
259
290
where
260
- V : fmt :: Debug ,
291
+ V : ToGodot ,
261
292
{
262
293
ConvertError :: with_kind_value ( ErrorKind :: FromVariant ( self ) , value)
263
294
}
295
+ }
264
296
265
- fn description ( & self ) -> String {
297
+ impl fmt:: Display for FromVariantError {
298
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
266
299
match self {
267
300
Self :: BadType { expected, actual } => {
268
301
// Note: wording is the same as in CallError::failed_param_conversion_engine()
269
- format ! ( "expected type `{expected:?}`, got `{actual:?}`" )
302
+ write ! ( f , "expected type `{expected:?}`, got `{actual:?}`" )
270
303
}
271
304
Self :: WrongClass { expected } => {
272
- format ! ( "expected class `{expected}`" )
305
+ write ! ( f , "expected class `{expected}`" )
273
306
}
274
307
}
275
308
}
276
309
}
277
310
278
311
fn __ensure_send_sync ( ) {
279
312
fn check < T : Send + Sync > ( ) { }
280
- check :: < ConvertError > ( ) ;
313
+ check :: < ErasedConvertError > ( ) ;
281
314
}
0 commit comments