mirror of
https://github.com/serde-rs/serde.git
synced 2025-10-02 23:35:26 +00:00
Merge pull request #117 from erickt/fix-json
Fix deriving traits for fully generic types.
This commit is contained in:
commit
447d08bd91
@ -55,10 +55,7 @@ pub fn expand_derive_serialize(
|
|||||||
&builder,
|
&builder,
|
||||||
&item,
|
&item,
|
||||||
&impl_generics,
|
&impl_generics,
|
||||||
builder.ty()
|
ty.clone(),
|
||||||
.ref_()
|
|
||||||
.lifetime("'__a")
|
|
||||||
.build_ty(ty.clone()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let where_clause = &impl_generics.where_clause;
|
let where_clause = &impl_generics.where_clause;
|
||||||
@ -184,7 +181,10 @@ fn serialize_tuple_struct(
|
|||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
ty,
|
builder.ty()
|
||||||
|
.ref_()
|
||||||
|
.lifetime("'__a")
|
||||||
|
.build_ty(ty.clone()),
|
||||||
fields,
|
fields,
|
||||||
impl_generics,
|
impl_generics,
|
||||||
);
|
);
|
||||||
@ -197,7 +197,7 @@ fn serialize_tuple_struct(
|
|||||||
serializer.visit_tuple_struct($type_name, Visitor {
|
serializer.visit_tuple_struct($type_name, Visitor {
|
||||||
value: self,
|
value: self,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -215,7 +215,10 @@ fn serialize_struct(
|
|||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
ty,
|
builder.ty()
|
||||||
|
.ref_()
|
||||||
|
.lifetime("'__a")
|
||||||
|
.build_ty(ty.clone()),
|
||||||
struct_def,
|
struct_def,
|
||||||
impl_generics,
|
impl_generics,
|
||||||
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
|
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
|
||||||
@ -229,7 +232,7 @@ fn serialize_struct(
|
|||||||
serializer.visit_struct($type_name, Visitor {
|
serializer.visit_struct($type_name, Visitor {
|
||||||
value: self,
|
value: self,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -383,7 +386,7 @@ fn serialize_tuple_variant(
|
|||||||
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
|
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
structure_ty,
|
structure_ty.clone(),
|
||||||
variant_ty,
|
variant_ty,
|
||||||
args.len(),
|
args.len(),
|
||||||
generics,
|
generics,
|
||||||
@ -392,9 +395,7 @@ fn serialize_tuple_variant(
|
|||||||
let value_expr = builder.expr().tuple()
|
let value_expr = builder.expr().tuple()
|
||||||
.with_exprs(
|
.with_exprs(
|
||||||
fields.iter().map(|field| {
|
fields.iter().map(|field| {
|
||||||
builder.expr()
|
builder.expr().id(field)
|
||||||
.addr_of()
|
|
||||||
.id(field)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
@ -405,7 +406,7 @@ fn serialize_tuple_variant(
|
|||||||
serializer.visit_enum_seq($type_name, $variant_index, $variant_name, Visitor {
|
serializer.visit_enum_seq($type_name, $variant_index, $variant_name, Visitor {
|
||||||
value: $value_expr,
|
value: $value_expr,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -435,9 +436,7 @@ fn serialize_struct_variant(
|
|||||||
let value_expr = builder.expr().tuple()
|
let value_expr = builder.expr().tuple()
|
||||||
.with_exprs(
|
.with_exprs(
|
||||||
fields.iter().map(|field| {
|
fields.iter().map(|field| {
|
||||||
builder.expr()
|
builder.expr().id(field)
|
||||||
.addr_of()
|
|
||||||
.id(field)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
@ -445,7 +444,7 @@ fn serialize_struct_variant(
|
|||||||
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
|
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
structure_ty,
|
structure_ty.clone(),
|
||||||
value_ty,
|
value_ty,
|
||||||
struct_def,
|
struct_def,
|
||||||
generics,
|
generics,
|
||||||
@ -462,7 +461,7 @@ fn serialize_struct_variant(
|
|||||||
serializer.visit_enum_map($type_name, $variant_index, $variant_name, Visitor {
|
serializer.visit_enum_map($type_name, $variant_index, $variant_name, Visitor {
|
||||||
value: $value_expr,
|
value: $value_expr,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -502,19 +501,12 @@ fn serialize_tuple_struct_visitor(
|
|||||||
.strip_bounds()
|
.strip_bounds()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Variants don't necessarily reference all generic lifetimes and type parameters,
|
|
||||||
// so to avoid a compilation failure, we'll just add a phantom type to capture these
|
|
||||||
// unused values.
|
|
||||||
let structure_ty = builder.ty()
|
|
||||||
.phantom_data()
|
|
||||||
.build(structure_ty);
|
|
||||||
|
|
||||||
(
|
(
|
||||||
quote_item!(cx,
|
quote_item!(cx,
|
||||||
struct Visitor $visitor_impl_generics $where_clause {
|
struct Visitor $visitor_impl_generics $where_clause {
|
||||||
state: usize,
|
state: usize,
|
||||||
value: $variant_ty,
|
value: $variant_ty,
|
||||||
_structure_ty: $structure_ty,
|
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
|
||||||
}
|
}
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
|
|
||||||
@ -590,19 +582,12 @@ fn serialize_struct_visitor<I>(
|
|||||||
.strip_bounds()
|
.strip_bounds()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Variants don't necessarily reference all generic lifetimes and type parameters,
|
|
||||||
// so to avoid a compilation failure, we'll just add a phantom type to capture these
|
|
||||||
// unused values.
|
|
||||||
let structure_ty = builder.ty()
|
|
||||||
.phantom_data()
|
|
||||||
.build(structure_ty);
|
|
||||||
|
|
||||||
(
|
(
|
||||||
quote_item!(cx,
|
quote_item!(cx,
|
||||||
struct Visitor $visitor_impl_generics $where_clause {
|
struct Visitor $visitor_impl_generics $where_clause {
|
||||||
state: usize,
|
state: usize,
|
||||||
value: $variant_ty,
|
value: $variant_ty,
|
||||||
_structure_ty: $structure_ty,
|
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
|
||||||
}
|
}
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
|
|
||||||
|
@ -131,6 +131,26 @@ enum Lifetimes<'a> {
|
|||||||
NoLifetimeMap { a: i32 },
|
NoLifetimeMap { a: i32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GenericStruct<T> {
|
||||||
|
x: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GenericTupleStruct<T>(T);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum GenericEnumSeq<T, E> {
|
||||||
|
Ok(T),
|
||||||
|
Err(E),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum GenericEnumMap<T, E> {
|
||||||
|
Ok { x: T },
|
||||||
|
Err { x: E },
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_named_unit() {
|
fn test_named_unit() {
|
||||||
let named_unit = NamedUnit;
|
let named_unit = NamedUnit;
|
||||||
@ -475,3 +495,29 @@ fn test_lifetimes() {
|
|||||||
"{\"NoLifetimeMap\":{\"a\":5}}"
|
"{\"NoLifetimeMap\":{\"a\":5}}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_generic() {
|
||||||
|
macro_rules! declare_tests {
|
||||||
|
($($ty:ty : $value:expr => $str:expr,)+) => {
|
||||||
|
$({
|
||||||
|
let value: $ty = $value;
|
||||||
|
|
||||||
|
let string = serde_json::to_string(&value).unwrap();
|
||||||
|
assert_eq!(string, $str);
|
||||||
|
|
||||||
|
let expected: $ty = serde_json::from_str(&string).unwrap();
|
||||||
|
assert_eq!(value, expected);
|
||||||
|
})+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_tests!(
|
||||||
|
GenericStruct<u32> : GenericStruct { x: 5 } => "{\"x\":5}",
|
||||||
|
GenericTupleStruct<u32> : GenericTupleStruct(5) => "[5]",
|
||||||
|
GenericEnumSeq<u32, u32> : GenericEnumSeq::Ok(5) => "{\"Ok\":[5]}",
|
||||||
|
GenericEnumSeq<u32, u32> : GenericEnumSeq::Err(5) => "{\"Err\":[5]}",
|
||||||
|
GenericEnumMap<u32, u32> : GenericEnumMap::Ok { x: 5 } => "{\"Ok\":{\"x\":5}}",
|
||||||
|
GenericEnumMap<u32, u32> : GenericEnumMap::Err { x: 5 } => "{\"Err\":{\"x\":5}}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user