Add "zero_copy_pod" feature.

The default "zero_copy" feature unsafe impls the bytemuck::Pod trait.

The new account(zero_copy_pod) and zero_copy_pod macros derive it
instead, which adds desired sanity checks like "has no padding".
This commit is contained in:
Christian Kamm 2022-12-05 13:54:19 +01:00
parent fbd238fb7c
commit 98dfe9de88
2 changed files with 41 additions and 13 deletions

View File

@ -66,6 +66,7 @@ pub fn account(
) -> proc_macro::TokenStream {
let mut namespace = "".to_string();
let mut is_zero_copy = false;
let mut is_zero_copy_pod = false;
let args_str = args.to_string();
let args: Vec<&str> = args_str.split(',').collect();
if args.len() > 2 {
@ -80,6 +81,8 @@ pub fn account(
.collect();
if ns == "zero_copy" {
is_zero_copy = true;
} else if ns == "zero_copy_pod" {
is_zero_copy_pod = true;
} else {
namespace = ns;
}
@ -123,17 +126,7 @@ pub fn account(
}
};
proc_macro::TokenStream::from({
if is_zero_copy {
quote! {
#[zero_copy]
#account_strct
#[automatically_derived]
unsafe impl #impl_gen anchor_lang::__private::bytemuck::Pod for #account_name #type_gen #where_clause {}
#[automatically_derived]
unsafe impl #impl_gen anchor_lang::__private::bytemuck::Zeroable for #account_name #type_gen #where_clause {}
let zero_copy_common = quote! {
#[automatically_derived]
impl #impl_gen anchor_lang::ZeroCopy for #account_name #type_gen #where_clause {}
@ -169,6 +162,27 @@ pub fn account(
}
#owner_impl
};
proc_macro::TokenStream::from({
if is_zero_copy {
quote! {
#[zero_copy]
#account_strct
#[automatically_derived]
unsafe impl #impl_gen anchor_lang::__private::bytemuck::Pod for #account_name #type_gen #where_clause {}
#[automatically_derived]
unsafe impl #impl_gen anchor_lang::__private::bytemuck::Zeroable for #account_name #type_gen #where_clause {}
#zero_copy_common
}
} else if is_zero_copy_pod {
quote! {
#[zero_copy_pod]
#account_strct
#zero_copy_common
}
} else {
quote! {
@ -313,6 +327,20 @@ pub fn zero_copy(
})
}
#[proc_macro_attribute]
pub fn zero_copy_pod(
_args: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let account_strct = parse_macro_input!(item as syn::ItemStruct);
proc_macro::TokenStream::from(quote! {
#[derive(anchor_lang::__private::ZeroCopyAccessor, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(C)]
#account_strct
})
}
/// Defines the program's ID. This should be used at the root of all Anchor
/// based programs.
#[proc_macro]

View File

@ -45,7 +45,7 @@ pub mod system_program;
mod vec;
pub use crate::bpf_upgradeable_state::*;
pub use anchor_attribute_access_control::access_control;
pub use anchor_attribute_account::{account, declare_id, zero_copy};
pub use anchor_attribute_account::{account, declare_id, zero_copy, zero_copy_pod};
pub use anchor_attribute_constant::constant;
pub use anchor_attribute_error::*;
pub use anchor_attribute_event::{emit, event};
@ -241,7 +241,7 @@ pub mod prelude {
context::Context, context::CpiContext, declare_id, emit, err, error, event, interface,
program, require, require_eq, require_gt, require_gte, require_keys_eq, require_keys_neq,
require_neq, solana_program::bpf_loader_upgradeable::UpgradeableLoaderState, source, state,
system_program::System, zero_copy, AccountDeserialize, AccountSerialize, Accounts,
system_program::System, zero_copy, zero_copy_pod, AccountDeserialize, AccountSerialize, Accounts,
AccountsExit, AnchorDeserialize, AnchorSerialize, Id, Key, Owner, ProgramData, Result,
ToAccountInfo, ToAccountInfos, ToAccountMetas,
};