borsh_derive/internals/deserialize/
mod.rs1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use syn::{ExprPath, Generics, Ident, Path};
4
5use super::{
6 attributes::{field, BoundType},
7 generics,
8};
9
10pub mod enums;
11pub mod structs;
12pub mod unions;
13
14struct GenericsOutput {
15 overrides: Vec<syn::WherePredicate>,
16 default_visitor: generics::FindTyParams,
17 deserialize_visitor: generics::FindTyParams,
18}
19
20impl GenericsOutput {
21 fn new(generics: &Generics) -> Self {
22 Self {
23 overrides: vec![],
24 deserialize_visitor: generics::FindTyParams::new(generics),
25 default_visitor: generics::FindTyParams::new(generics),
26 }
27 }
28 fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) {
29 let de_trait: Path = syn::parse2(quote! { #cratename::de::BorshDeserialize }).unwrap();
30 let default_trait: Path = syn::parse2(quote! { core::default::Default }).unwrap();
31 let de_predicates =
32 generics::compute_predicates(self.deserialize_visitor.process_for_bounds(), &de_trait);
33 let default_predicates =
34 generics::compute_predicates(self.default_visitor.process_for_bounds(), &default_trait);
35 where_clause.predicates.extend(de_predicates);
36 where_clause.predicates.extend(default_predicates);
37 where_clause.predicates.extend(self.overrides);
38 }
39}
40
41fn process_field(
42 field: &syn::Field,
43 cratename: &Path,
44 body: &mut TokenStream2,
45 generics: &mut GenericsOutput,
46) -> syn::Result<()> {
47 let parsed = field::Attributes::parse(&field.attrs)?;
48
49 generics
50 .overrides
51 .extend(parsed.collect_bounds(BoundType::Deserialize));
52 let needs_bounds_derive = parsed.needs_bounds_derive(BoundType::Deserialize);
53
54 let field_name = field.ident.as_ref();
55 let delta = if parsed.skip {
56 if needs_bounds_derive {
57 generics.default_visitor.visit_field(field);
58 }
59 field_default_output(field_name)
60 } else {
61 if needs_bounds_derive {
62 generics.deserialize_visitor.visit_field(field);
63 }
64 field_output(field_name, cratename, parsed.deserialize_with)
65 };
66 body.extend(delta);
67 Ok(())
68}
69
70fn field_output(
73 field_name: Option<&Ident>,
74 cratename: &Path,
75 deserialize_with: Option<ExprPath>,
76) -> TokenStream2 {
77 let default_path: ExprPath =
78 syn::parse2(quote! { #cratename::BorshDeserialize::deserialize_reader }).unwrap();
79 let path: ExprPath = deserialize_with.unwrap_or(default_path);
80 if let Some(field_name) = field_name {
81 quote! {
82 #field_name: #path(reader)?,
83 }
84 } else {
85 quote! {
86 #path(reader)?,
87 }
88 }
89}
90
91fn field_default_output(field_name: Option<&Ident>) -> TokenStream2 {
94 if let Some(field_name) = field_name {
95 quote! {
96 #field_name: core::default::Default::default(),
97 }
98 } else {
99 quote! { core::default::Default::default(), }
100 }
101}