1use std::collections::BTreeMap;
2
3use anchor_syn::idl::{IdlField, IdlTypeDefinition};
4use proc_macro2::TokenStream;
5use quote::{format_ident, quote};
6
7use crate::{generate_fields, get_field_list_properties, StructOpts};
8
9pub fn generate_account(
11 defs: &[IdlTypeDefinition],
12 account_name: &str,
13 fields: &[IdlField],
14 opts: StructOpts,
15) -> TokenStream {
16 let props = get_field_list_properties(defs, fields);
17
18 let derive_copy = if props.can_copy && !opts.zero_copy {
19 quote! {
20 #[derive(Copy)]
21 }
22 } else {
23 quote! {}
24 };
25 let derive_default = if props.can_derive_default {
26 quote! {
27 #[derive(Default)]
28 }
29 } else {
30 quote! {}
31 };
32 let derive_account = if opts.zero_copy {
33 let repr = if opts.packed {
34 quote! {
35 #[repr(packed)]
36 }
37 } else {
38 quote! {
39 #[repr(C)]
40 }
41 };
42 quote! {
43 #[account(zero_copy)]
44 #repr
45 }
46 } else {
47 quote! {
48 #[account]
49 }
50 };
51
52 let doc = format!(" Account: {}", account_name);
53 let struct_name = format_ident!("{}", account_name);
54 let fields_rendered = generate_fields(fields);
55 quote! {
56 #derive_account
57 #[doc = #doc]
58 #derive_copy
59 #derive_default
60 pub struct #struct_name {
61 #fields_rendered
62 }
63 }
64}
65
66pub fn generate_accounts(
68 typedefs: &[IdlTypeDefinition],
69 account_defs: &[IdlTypeDefinition],
70 struct_opts: &BTreeMap<String, StructOpts>,
71) -> TokenStream {
72 let defined = account_defs.iter().map(|def| match &def.ty {
73 anchor_syn::idl::IdlTypeDefinitionTy::Struct { fields } => {
74 let opts = struct_opts.get(&def.name).copied().unwrap_or_default();
75 generate_account(typedefs, &def.name, fields, opts)
76 }
77 anchor_syn::idl::IdlTypeDefinitionTy::Enum { .. } => {
78 panic!("unexpected enum account");
79 }
80 });
81 quote! {
82 #(#defined)*
83 }
84}