anchor_cereal_derive/
lib.rs1use 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}