23
23
//! All error types provide an `into_src` method that converts the error into
24
24
//! the source value underlying the failed conversion.
25
25
26
- use core:: { convert:: Infallible , fmt, marker :: PhantomData , ops:: Deref } ;
26
+ use core:: { convert:: Infallible , fmt, ops:: Deref } ;
27
27
28
- use crate :: TryFromBytes ;
28
+ use crate :: { util :: SendSyncPhantomData , KnownLayout , TryFromBytes } ;
29
29
#[ cfg( doc) ]
30
30
use crate :: { FromBytes , Ref } ;
31
31
@@ -82,18 +82,27 @@ impl<A: fmt::Display, S: fmt::Display, V: fmt::Display> fmt::Display for Convert
82
82
}
83
83
}
84
84
85
+ #[ cfg( any( feature = "std" , test) ) ]
86
+ impl < A , S , V > std:: error:: Error for ConvertError < A , S , V >
87
+ where
88
+ A : fmt:: Display + fmt:: Debug ,
89
+ S : fmt:: Display + fmt:: Debug ,
90
+ V : fmt:: Display + fmt:: Debug ,
91
+ {
92
+ }
93
+
85
94
/// The error emitted if the conversion source is improperly aligned.
86
95
#[ derive( PartialEq , Eq ) ]
87
96
pub struct AlignmentError < Src , Dst : ?Sized > {
88
97
/// The source value involved in the conversion.
89
98
src : Src ,
90
99
/// The inner destination type inolved in the conversion.
91
- dst : PhantomData < Dst > ,
100
+ dst : SendSyncPhantomData < Dst > ,
92
101
}
93
102
94
103
impl < Src , Dst : ?Sized > AlignmentError < Src , Dst > {
95
104
pub ( crate ) fn new ( src : Src ) -> Self {
96
- Self { src, dst : PhantomData }
105
+ Self { src, dst : SendSyncPhantomData :: default ( ) }
97
106
}
98
107
99
108
/// Produces the source underlying the failed conversion.
@@ -103,11 +112,11 @@ impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
103
112
}
104
113
105
114
pub ( crate ) fn with_src < NewSrc > ( self , new_src : NewSrc ) -> AlignmentError < NewSrc , Dst > {
106
- AlignmentError { src : new_src, dst : PhantomData }
115
+ AlignmentError { src : new_src, dst : SendSyncPhantomData :: default ( ) }
107
116
}
108
117
109
118
pub ( crate ) fn map_src < NewSrc > ( self , f : impl Fn ( Src ) -> NewSrc ) -> AlignmentError < NewSrc , Dst > {
110
- AlignmentError { src : f ( self . src ) , dst : PhantomData }
119
+ AlignmentError { src : f ( self . src ) , dst : SendSyncPhantomData :: default ( ) }
111
120
}
112
121
113
122
pub ( crate ) fn into < S , V > ( self ) -> ConvertError < Self , S , V > {
@@ -126,9 +135,10 @@ impl<Src, Dst: ?Sized> fmt::Debug for AlignmentError<Src, Dst> {
126
135
// The bounds on this impl are intentionally conservative, and can be relaxed
127
136
// either once a `?Sized` alignment accessor is stabilized, or by storing the
128
137
// alignment as a runtime value.
129
- impl < Src , Dst > fmt:: Display for AlignmentError < Src , Dst >
138
+ impl < Src , Dst : ? Sized > fmt:: Display for AlignmentError < Src , Dst >
130
139
where
131
140
Src : Deref ,
141
+ Dst : KnownLayout ,
132
142
{
133
143
#[ inline]
134
144
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -139,14 +149,22 @@ where
139
149
f. write_str ( "the conversion failed because the address of the source (a multiple of " ) ?;
140
150
addr_align. fmt ( f) ?;
141
151
f. write_str ( ") is not a multiple of the alignment (" ) ?;
142
- core :: mem :: align_of :: < Dst > ( ) . fmt ( f) ?;
152
+ <Dst as KnownLayout > :: LAYOUT . align . get ( ) . fmt ( f) ?;
143
153
f. write_str ( ") of the destination type: " ) ?;
144
154
f. write_str ( core:: any:: type_name :: < Dst > ( ) ) ?;
145
155
Ok ( ( ) )
146
156
}
147
157
}
148
158
149
- impl < Src , Dst , S , V > From < AlignmentError < Src , Dst > >
159
+ #[ cfg( any( feature = "std" , test) ) ]
160
+ impl < Src , Dst : ?Sized > std:: error:: Error for AlignmentError < Src , Dst >
161
+ where
162
+ Src : Deref ,
163
+ Dst : KnownLayout ,
164
+ {
165
+ }
166
+
167
+ impl < Src , Dst : ?Sized , S , V > From < AlignmentError < Src , Dst > >
150
168
for ConvertError < AlignmentError < Src , Dst > , S , V >
151
169
{
152
170
#[ inline]
@@ -161,12 +179,12 @@ pub struct SizeError<Src, Dst: ?Sized> {
161
179
/// The source value involved in the conversion.
162
180
src : Src ,
163
181
/// The inner destination type inolved in the conversion.
164
- dst : PhantomData < Dst > ,
182
+ dst : SendSyncPhantomData < Dst > ,
165
183
}
166
184
167
185
impl < Src , Dst : ?Sized > SizeError < Src , Dst > {
168
186
pub ( crate ) fn new ( src : Src ) -> Self {
169
- Self { src, dst : PhantomData }
187
+ Self { src, dst : SendSyncPhantomData :: default ( ) }
170
188
}
171
189
172
190
/// Produces the source underlying the failed conversion.
@@ -177,17 +195,17 @@ impl<Src, Dst: ?Sized> SizeError<Src, Dst> {
177
195
178
196
/// Sets the source value associated with the conversion error.
179
197
pub ( crate ) fn with_src < NewSrc > ( self , new_src : NewSrc ) -> SizeError < NewSrc , Dst > {
180
- SizeError { src : new_src, dst : PhantomData }
198
+ SizeError { src : new_src, dst : SendSyncPhantomData :: default ( ) }
181
199
}
182
200
183
201
/// Maps the source value associated with the conversion error.
184
202
pub ( crate ) fn map_src < NewSrc > ( self , f : impl Fn ( Src ) -> NewSrc ) -> SizeError < NewSrc , Dst > {
185
- SizeError { src : f ( self . src ) , dst : PhantomData }
203
+ SizeError { src : f ( self . src ) , dst : SendSyncPhantomData :: default ( ) }
186
204
}
187
205
188
206
/// Sets the destination type associated with the conversion error.
189
207
pub ( crate ) fn with_dst < NewDst : ?Sized > ( self ) -> SizeError < Src , NewDst > {
190
- SizeError { src : self . src , dst : PhantomData }
208
+ SizeError { src : self . src , dst : SendSyncPhantomData :: default ( ) }
191
209
}
192
210
193
211
/// Converts the error into a general [`ConvertError`].
@@ -206,17 +224,26 @@ impl<Src, Dst: ?Sized> fmt::Debug for SizeError<Src, Dst> {
206
224
/// Produces a human-readable error message.
207
225
impl < Src , Dst : ?Sized > fmt:: Display for SizeError < Src , Dst >
208
226
where
209
- Src : Deref ,
227
+ Dst : KnownLayout ,
210
228
{
211
229
#[ inline]
212
230
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
213
- f. write_str ( "the conversion failed because the source was incorrectly sized to complete the conversion into the destination type: " ) ?;
231
+ f. write_str ( "the conversion failed because the source was incorrectly sized to complete the conversion into the destination type" ) ?;
232
+ if let crate :: SizeInfo :: Sized { size } = Dst :: LAYOUT . size_info {
233
+ f. write_str ( " (" ) ?;
234
+ size. fmt ( f) ?;
235
+ f. write_str ( " bytes)" ) ?;
236
+ }
237
+ f. write_str ( ": " ) ?;
214
238
f. write_str ( core:: any:: type_name :: < Dst > ( ) ) ?;
215
239
Ok ( ( ) )
216
240
}
217
241
}
218
242
219
- impl < Src , Dst , A , V > From < SizeError < Src , Dst > > for ConvertError < A , SizeError < Src , Dst > , V > {
243
+ #[ cfg( any( feature = "std" , test) ) ]
244
+ impl < Src , Dst : ?Sized > std:: error:: Error for SizeError < Src , Dst > where Dst : KnownLayout { }
245
+
246
+ impl < Src , Dst : ?Sized , A , V > From < SizeError < Src , Dst > > for ConvertError < A , SizeError < Src , Dst > , V > {
220
247
#[ inline]
221
248
fn from ( err : SizeError < Src , Dst > ) -> Self {
222
249
Self :: Size ( err)
@@ -229,12 +256,12 @@ pub struct ValidityError<Src, Dst: ?Sized + TryFromBytes> {
229
256
/// The source value involved in the conversion.
230
257
pub ( crate ) src : Src ,
231
258
/// The inner destination type inolved in the conversion.
232
- dst : PhantomData < Dst > ,
259
+ dst : SendSyncPhantomData < Dst > ,
233
260
}
234
261
235
262
impl < Src , Dst : ?Sized + TryFromBytes > ValidityError < Src , Dst > {
236
263
pub ( crate ) fn new ( src : Src ) -> Self {
237
- Self { src, dst : PhantomData }
264
+ Self { src, dst : SendSyncPhantomData :: default ( ) }
238
265
}
239
266
240
267
/// Produces the source underlying the failed conversion.
@@ -245,7 +272,7 @@ impl<Src, Dst: ?Sized + TryFromBytes> ValidityError<Src, Dst> {
245
272
246
273
/// Maps the source value associated with the conversion error.
247
274
pub ( crate ) fn map_src < NewSrc > ( self , f : impl Fn ( Src ) -> NewSrc ) -> ValidityError < NewSrc , Dst > {
248
- ValidityError { src : f ( self . src ) , dst : PhantomData }
275
+ ValidityError { src : f ( self . src ) , dst : SendSyncPhantomData :: default ( ) }
249
276
}
250
277
251
278
/// Converts the error into a general [`ConvertError`].
@@ -262,10 +289,7 @@ impl<Src, Dst: ?Sized + TryFromBytes> fmt::Debug for ValidityError<Src, Dst> {
262
289
}
263
290
264
291
/// Produces a human-readable error message.
265
- impl < Src , Dst : ?Sized + TryFromBytes > fmt:: Display for ValidityError < Src , Dst >
266
- where
267
- Src : Deref ,
268
- {
292
+ impl < Src , Dst : ?Sized + TryFromBytes > fmt:: Display for ValidityError < Src , Dst > {
269
293
#[ inline]
270
294
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
271
295
f. write_str ( "the conversion failed because the source bytes are not a valid value of the destination type: " ) ?;
@@ -274,6 +298,9 @@ where
274
298
}
275
299
}
276
300
301
+ #[ cfg( any( feature = "std" , test) ) ]
302
+ impl < Src , Dst : ?Sized + TryFromBytes > std:: error:: Error for ValidityError < Src , Dst > { }
303
+
277
304
impl < Src , Dst : ?Sized + TryFromBytes , A , S > From < ValidityError < Src , Dst > >
278
305
for ConvertError < A , S , ValidityError < Src , Dst > >
279
306
{
@@ -395,16 +422,55 @@ impl<Src, Dst: ?Sized + TryFromBytes> TryReadError<Src, Dst> {
395
422
}
396
423
397
424
#[ cfg( test) ]
398
- mod test {
425
+ mod tests {
399
426
use super :: * ;
400
427
428
+ #[ test]
429
+ fn test_send_sync ( ) {
430
+ // Test that all error types are `Send + Sync` even if `Dst: !Send +
431
+ // !Sync`.
432
+
433
+ #[ allow( dead_code) ]
434
+ fn is_send_sync < T : Send + Sync > ( _t : T ) { }
435
+
436
+ #[ allow( dead_code) ]
437
+ fn alignment_err_is_send_sync < Src : Send + Sync , Dst > ( err : AlignmentError < Src , Dst > ) {
438
+ is_send_sync ( err)
439
+ }
440
+
441
+ #[ allow( dead_code) ]
442
+ fn size_err_is_send_sync < Src : Send + Sync , Dst > ( err : SizeError < Src , Dst > ) {
443
+ is_send_sync ( err)
444
+ }
445
+
446
+ #[ allow( dead_code) ]
447
+ fn validity_err_is_send_sync < Src : Send + Sync , Dst : TryFromBytes > (
448
+ err : ValidityError < Src , Dst > ,
449
+ ) {
450
+ is_send_sync ( err)
451
+ }
452
+
453
+ #[ allow( dead_code) ]
454
+ fn convert_error_is_send_sync < Src : Send + Sync , Dst : TryFromBytes > (
455
+ err : ConvertError <
456
+ AlignmentError < Src , Dst > ,
457
+ SizeError < Src , Dst > ,
458
+ ValidityError < Src , Dst > ,
459
+ > ,
460
+ ) {
461
+ is_send_sync ( err)
462
+ }
463
+ }
464
+
401
465
#[ test]
402
466
fn alignment_display ( ) {
403
467
#[ repr( C , align( 128 ) ) ]
404
468
struct Aligned {
405
469
bytes : [ u8 ; 128 ] ,
406
470
}
407
471
472
+ impl_known_layout ! ( elain:: Align :: <8 >) ;
473
+
408
474
let aligned = Aligned { bytes : [ 0 ; 128 ] } ;
409
475
410
476
assert_eq ! (
@@ -434,6 +500,11 @@ mod test {
434
500
SizeError :: <_, [ u8 ] >:: new( & [ 0u8 ; 1 ] [ ..] ) . to_string( ) ,
435
501
"the conversion failed because the source was incorrectly sized to complete the conversion into the destination type: [u8]"
436
502
) ;
503
+
504
+ assert_eq ! (
505
+ SizeError :: <_, [ u8 ; 2 ] >:: new( & [ 0u8 ; 1 ] [ ..] ) . to_string( ) ,
506
+ "the conversion failed because the source was incorrectly sized to complete the conversion into the destination type (2 bytes): [u8; 2]"
507
+ ) ;
437
508
}
438
509
439
510
#[ test]
0 commit comments