1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use crate::parse_type::NamedFieldsInfo;
use proc_macro2::TokenStream;
use quote::quote;
pub fn generate_named_fields_impl(
fields: &NamedFieldsInfo,
err_ty: &syn::Type,
create: TokenStream,
) -> TokenStream {
let NamedFieldsInfo {
field_names,
field_tys,
field_defaults,
field_errs,
field_from_fns,
field_from_errors: _,
field_maps,
missing_field_errors,
key_names,
unknown_key,
needs_predicate: _,
} = fields;
quote! {
// Start by declaring all the fields as mutable optionals
// Their initial value is given by the precomputed `#field_defaults`,
// see [NamedFieldsInfo] and [NamedFieldsInfo::parse].
//
// The initial value of #field_names is `None` if the field has no initial value and
// thus must be given by the map, and `Some` otherwise.
#(
let mut #field_names : ::deserr::FieldState<_> = #field_defaults ;
)*
// We traverse the entire map instead of looking for specific keys, because we want
// to handle the case where a key is unknown and the attribute `deny_unknown_fields` was used.
for (deserr_key__, deserr_value__) in ::deserr::Map::into_iter(deserr_map__) {
match deserr_key__.as_str() {
// For each known key, look at the corresponding value and try to deserialize it
#(
#key_names => {
#field_names = match
<#field_tys as ::deserr::Deserr<#field_errs>>::deserialize_from_value(
::deserr::IntoValue::into_value(deserr_value__),
deserr_location__.push_key(deserr_key__.as_str())
) {
::std::result::Result::Ok(x) => {
#field_from_fns
},
::std::result::Result::Err(e) => {
deserr_error__ = match <#err_ty as ::deserr::MergeWithError<_>>::merge(
deserr_error__,
e,
deserr_location__.push_key(deserr_key__.as_str())
) {
::std::ops::ControlFlow::Continue(e) => ::std::option::Option::Some(e),
::std::ops::ControlFlow::Break(e) => return ::std::result::Result::Err(e),
};
::deserr::FieldState::Err
}
};
}
)*
// For an unknown key, use the precomputed #unknown_key token stream
deserr_key__ => {
#unknown_key
}
}
}
// Now we check whether any field was missing
#(
if #field_names .is_missing() {
#missing_field_errors
}
)*
if let Some(deserr_error__) = deserr_error__ {
::std::result::Result::Err(deserr_error__)
} else {
// If the deserialization was successful, then all #field_names are `Some(..)`
// Otherwise, an error was thrown earlier
::std::result::Result::Ok(#create {
#(
#field_names : #field_names.map(#field_maps).unwrap(),
)*
})
}
}
}