use crate::Error; use quote::quote; pub fn generate(error: Error) -> proc_macro2::TokenStream { let error_enum = &error.raw_enum; let enum_name = &error.ident; // Each arm of the `match` statement for implementing `std::fmt::Display` // on the user defined error code. let display_variant_dispatch: Vec = error .raw_enum .variants .iter() .enumerate() .map(|(idx, variant)| { let ident = &variant.ident; let error_code = &error.codes[idx]; let display_msg = match &error_code.msg { None => { quote! { ::fmt(self, fmt) } } Some(msg) => { quote! { write!(fmt, #msg) } } }; quote! { #enum_name::#ident => #display_msg } }) .collect(); // Each arm of the `match` statement for implementing the `name` function // on the user defined error code. let name_variant_dispatch: Vec = error .raw_enum .variants .iter() .map(|variant| { let ident = &variant.ident; let ident_name = ident.to_string(); quote! { #enum_name::#ident => #ident_name.to_string() } }) .collect(); let offset = match error.args { None => quote! { anchor_lang::error::ERROR_CODE_OFFSET}, Some(args) => { let offset = &args.offset; quote! { #offset } } }; quote! { #[derive(std::fmt::Debug, Clone, Copy)] #[repr(u32)] #error_enum impl #enum_name { /// Gets the name of this [#enum_name]. pub fn name(&self) -> String { match self { #(#name_variant_dispatch),* } } } impl From<#enum_name> for u32 { fn from(e: #enum_name) -> u32 { e as u32 + #offset } } impl From<#enum_name> for anchor_lang::error::Error { fn from(error_code: #enum_name) -> anchor_lang::error::Error { anchor_lang::error::Error::from( anchor_lang::error::AnchorError { error_name: error_code.name(), error_code_number: error_code.into(), error_msg: error_code.to_string(), error_origin: None, compared_values: None } ) } } impl std::fmt::Display for #enum_name { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { match self { #(#display_variant_dispatch),* } } } } }