Skip to content

Commit aff384c

Browse files
committed
Now working
1 parent 3e61501 commit aff384c

3 files changed

Lines changed: 26 additions & 5 deletions

File tree

epserde-derive/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
292292

293293
s.fields.iter().for_each(|field| {
294294
let ty = &field.ty.to_token_stream().to_string();
295-
if generics_names_raw.contains(ty) || ty.starts_with("PhantomDeserData") {
295+
if ty.starts_with("PhantomDeserData") {
296+
methods.push(syn::parse_quote!(_deserialize_eps_inner_special));
297+
} else if generics_names_raw.contains(ty) {
296298
methods.push(syn::parse_quote!(_deserialize_eps_inner));
297299
} else {
298300
methods.push(syn::parse_quote!(_deserialize_full_inner));
@@ -608,7 +610,11 @@ pub fn epserde_derive(input: TokenStream) -> TokenStream {
608610
bounds: bounds_des,
609611
}));
610612

611-
if generics_names_raw.contains(&ty.to_token_stream().to_string()) {
613+
// TODO don't do just string comparison
614+
let ty = ty.to_token_stream().to_string();
615+
if ty.starts_with("PhantomDeserData") {
616+
methods.push(syn::parse_quote!(_deserialize_eps_inner_special));
617+
} else if generics_names_raw.contains(&ty) {
612618
methods.push(syn::parse_quote!(_deserialize_eps_inner));
613619
} else {
614620
methods.push(syn::parse_quote!(_deserialize_full_inner));

epserde/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#[cfg(all(feature = "alloc", not(feature = "std")))]
1212
extern crate alloc;
1313

14-
use core::{hash::Hash, marker::PhantomData};
14+
use core::{hash::Hash, marker::PhantomData, mem::transmute};
1515

1616
#[cfg(feature = "derive")]
1717
pub use epserde_derive::{Epserde, TypeInfo};
@@ -72,6 +72,21 @@ impl<T: ?Sized> PhantomDeserData<T> {
7272
}
7373
}
7474

75+
impl<T: ?Sized + DeserializeInner> PhantomDeserData<T> {
76+
#[inline(always)]
77+
pub unsafe fn _deserialize_eps_inner_special<'a>(
78+
_backend: &mut SliceWithPos<'a>,
79+
) -> deser::Result<PhantomDeserData<T::DeserType<'a>>> {
80+
// SAFETY: types are zero-length
81+
Ok(unsafe {
82+
transmute::<
83+
<PhantomDeserData<T> as DeserializeInner>::DeserType<'a>,
84+
PhantomDeserData<T::DeserType<'a>>,
85+
>(PhantomDeserData(PhantomData))
86+
})
87+
}
88+
}
89+
7590
impl<T: ?Sized> CopyType for PhantomDeserData<T> {
7691
type Copy = Zero;
7792
}

epserde/tests/test_phantom.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ fn test_only_phantom() {
160160
struct DataWithPhantomDeserData<T> {
161161
data: T,
162162
// This will deserialize to PhantomData<T::DeserType<'a>>
163-
phantom: PhantomDeserData<PhantomData<T>>,
163+
phantom: PhantomDeserData<T>,
164164
}
165165

166166
/// Test that PhantomDeserData works correctly with generic types that are transformed during deserialization.
@@ -193,5 +193,5 @@ fn test_deser_phantom() {
193193

194194
// The phantom field should be PhantomData<&[i32]> (the DeserType of Vec<i32>)
195195
// We can't directly compare PhantomData types, but we can verify the deserialization worked
196-
let _phantom_check: PhantomDeserData<PhantomData<&[i32]>> = eps.phantom;
196+
let _phantom_check: PhantomDeserData<&[i32]> = eps.phantom;
197197
}

0 commit comments

Comments
 (0)