1
1
use std:: {
2
+ any:: TypeId ,
2
3
borrow:: Cow ,
3
4
collections:: HashMap ,
4
5
future:: Future ,
@@ -302,6 +303,44 @@ pub trait Deserializer<'s>: std::fmt::Debug {
302
303
}
303
304
}
304
305
306
+ mod mini_typeid {
307
+ // vendored straight from https://github.com/dtolnay/typeid — which is dual-licensed under
308
+ // MIT and Apache-2.0, just like merde.
309
+ //
310
+ // We don't really need const type_id construction or older rustc support, so this is a minimal
311
+ // take on it.
312
+
313
+ use std:: { any:: TypeId , marker:: PhantomData } ;
314
+
315
+ #[ must_use]
316
+ #[ inline( always) ]
317
+ pub fn of < T > ( ) -> TypeId
318
+ where
319
+ T : ?Sized ,
320
+ {
321
+ trait NonStaticAny {
322
+ fn get_type_id ( & self ) -> TypeId
323
+ where
324
+ Self : ' static ;
325
+ }
326
+
327
+ impl < T : ?Sized > NonStaticAny for PhantomData < T > {
328
+ #[ inline( always) ]
329
+ fn get_type_id ( & self ) -> TypeId
330
+ where
331
+ Self : ' static ,
332
+ {
333
+ TypeId :: of :: < T > ( )
334
+ }
335
+ }
336
+
337
+ let phantom_data = PhantomData :: < T > ;
338
+ NonStaticAny :: get_type_id ( unsafe {
339
+ std:: mem:: transmute :: < & dyn NonStaticAny , & ( dyn NonStaticAny + ' static ) > ( & phantom_data)
340
+ } )
341
+ }
342
+ }
343
+
305
344
/// Allows filling in a field of a struct while deserializing.
306
345
///
307
346
/// Enforces some type safety at runtime, by carrying lifetimes
@@ -310,7 +349,8 @@ pub trait Deserializer<'s>: std::fmt::Debug {
310
349
/// actually badly UB though. I should ask miri.
311
350
pub struct FieldSlot < ' s , ' borrow > {
312
351
option : * mut Option < ( ) > ,
313
- type_name_of_option_field : & ' static str ,
352
+ type_id_of_field : TypeId ,
353
+ type_name_of_field : & ' static str ,
314
354
_phantom : PhantomData < ( & ' s ( ) , & ' borrow mut ( ) ) > ,
315
355
}
316
356
@@ -323,15 +363,22 @@ impl<'s, 'borrow> FieldSlot<'s, 'borrow> {
323
363
option : unsafe {
324
364
std:: mem:: transmute :: < * mut Option < T > , * mut Option < ( ) > > ( option as * mut _ )
325
365
} ,
326
- type_name_of_option_field : std:: any:: type_name :: < Option < T > > ( ) ,
366
+ type_id_of_field : mini_typeid:: of :: < T > ( ) ,
367
+ type_name_of_field : std:: any:: type_name :: < T > ( ) ,
327
368
_phantom : PhantomData ,
328
369
}
329
370
}
330
371
331
372
/// Fill this field with a value.
332
373
pub fn fill < T : ' s > ( self , value : T ) {
333
- let type_name_of_option_value = std:: any:: type_name :: < Option < T > > ( ) ;
334
- assert_eq ! ( self . type_name_of_option_field, type_name_of_option_value) ;
374
+ let type_id_of_value = mini_typeid:: of :: < T > ( ) ;
375
+ assert_eq ! (
376
+ self . type_id_of_field,
377
+ type_id_of_value,
378
+ "tried to assign a \x1b [33m{}\x1b [0m to a slot of type \x1b [34m{}\x1b [0m" ,
379
+ std:: any:: type_name:: <T >( ) ,
380
+ self . type_name_of_field,
381
+ ) ;
335
382
336
383
unsafe {
337
384
let option_ptr: * mut Option < T > = std:: mem:: transmute ( self . option ) ;
@@ -1023,3 +1070,6 @@ impl Future for ReturnPendingOnce {
1023
1070
}
1024
1071
}
1025
1072
}
1073
+
1074
+ #[ cfg( test) ]
1075
+ mod tests;
0 commit comments