anchor_cereal_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn;
4
5fn parse_array_ast(ast_data: syn::Data) -> (std::boxed::Box<syn::Type>, syn::Expr) {
6  match ast_data {
7    syn::Data::Struct(syn::DataStruct {
8      fields: syn::Fields::Named(syn::FieldsNamed { named, .. }),
9      ..
10    }) => {
11      if named.len() > 1 {
12        todo!();
13      }
14
15      match named.first() {
16        Some(syn::Field {
17          ty: syn::Type::Array(syn::TypeArray { elem, len, .. }),
18          ..
19        }) => (elem.clone(), len.clone()),
20        _ => panic!("Cannot derive: expected struct with a single field `value: [T; N]`"),
21      }
22    }
23    _ => panic!("Cannot derive: expected struct with named fields"),
24  }
25}
26
27#[proc_macro_derive(AnchorDefaultArray)]
28pub fn anchor_default_array_derive(input: TokenStream) -> TokenStream {
29  let ast: syn::DeriveInput = syn::parse(input).unwrap();
30  let name = ast.ident;
31  let (_, len) = parse_array_ast(ast.data);
32
33  let gen = quote! {
34    impl Default for #name {
35      #[inline]
36      fn default() -> Self {
37        Self { value: [Default::default(); #len] }
38      }
39    }
40  };
41
42  gen.into()
43}
44
45#[proc_macro_derive(AnchorSerializeArray)]
46pub fn anchor_serialize_array_derive(input: TokenStream) -> TokenStream {
47  let ast: syn::DeriveInput = syn::parse(input).unwrap();
48  let name = ast.ident;
49
50  let gen = quote! {
51    impl borsh::BorshSerialize for #name {
52      #[inline]
53      fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
54        for el in self.value.iter() {
55          el.serialize(writer)?;
56        }
57        Ok(())
58      }
59    }
60  };
61
62  gen.into()
63}
64
65#[proc_macro_derive(AnchorDeserializeArray)]
66pub fn anchor_deserialize_array_derive(input: TokenStream) -> TokenStream {
67  let ast: syn::DeriveInput = syn::parse(input).unwrap();
68  let name = ast.ident;
69  let (ty, len) = parse_array_ast(ast.data);
70
71  let gen = quote! {
72    impl borsh::BorshDeserialize for #name {
73      #[inline]
74      fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
75        let mut items = Vec::with_capacity(#len);
76
77        for i in 0..#len {
78          items.push(#ty::deserialize(buf)?);
79        }
80
81        return Ok(Self { value: items.try_into().unwrap() });
82      }
83    }
84
85    impl std::ops::Deref for #name {
86      type Target = [#ty; #len];
87
88      fn deref(&self) -> &Self::Target {
89        &self.value
90      }
91    }
92
93    impl std::ops::DerefMut for #name {
94      fn deref_mut(&mut self) -> &mut Self::Target {
95        &mut self.value
96      }
97    }
98
99    impl From<[#ty; #len]> for #name {
100      fn from(value: [#ty; #len]) -> Self {
101        Self { value }
102      }
103    }
104  };
105
106  gen.into()
107}
108
109#[proc_macro_derive(AnchorSerializeSkip)]
110pub fn anchor_serialize_skip_derive(_input: TokenStream) -> TokenStream {
111  TokenStream::new()
112}
113
114#[proc_macro_derive(AnchorDeserializeSkip)]
115pub fn anchor_deserialize_skip_derive(_input: TokenStream) -> TokenStream {
116  TokenStream::new()
117}