feat(codegen): Add #[serde(deserialize_with="...")]

This allows a field to be deserialized with an expression instead
of the default deserializer. This simplifies deserializing a struct
or enum that contains an external type that doesn't implement
`serde::Deserialize`. This expression is passed a variable
`deserializer` that needs to be used to deserialize the expression.
This commit is contained in:
Erick Tryzelaar
2016-02-15 20:43:11 -08:00
parent 001cb7ab01
commit 40f8e6b061
3 changed files with 207 additions and 15 deletions
+17 -13
View File
@@ -991,6 +991,12 @@ fn deserialize_map(
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let field_attrs: Vec<_> = try!(
fields.iter()
.map(|field| attr::FieldAttrs::from_field(cx, container_ty, generics, field))
.collect()
);
// Declare each field.
let let_values: Vec<ast::Stmt> = field_names.iter()
.map(|field_name| quote_stmt!(cx, let mut $field_name = None;).unwrap())
@@ -1007,26 +1013,24 @@ fn deserialize_map(
};
// Match arms to extract a value for a field.
let value_arms: Vec<ast::Arm> = field_names.iter()
.map(|field_name| {
let value_arms = field_attrs.iter().zip(field_names.iter())
.map(|(field_attr, field_name)| {
let expr = match field_attr.deserialize_with() {
Some(expr) => expr.clone(),
None => quote_expr!(cx, visitor.visit_value()),
};
quote_arm!(cx,
__Field::$field_name => {
$field_name = Some(try!(visitor.visit_value()));
$field_name = Some(try!($expr));
}
)
})
.chain(ignored_arm.into_iter())
.collect();
.collect::<Vec<_>>();
let extract_values = fields.iter()
.zip(field_names.iter())
.map(|(field, field_name)| {
let field_attr = try!(
attr::FieldAttrs::from_field(cx,
container_ty,
generics,
field)
);
let extract_values = field_attrs.iter().zip(field_names.iter())
.map(|(field_attr, field_name)| {
let missing_expr = field_attr.expr_is_missing();
Ok(quote_stmt!(cx,