anchor_syn/codegen/
error.rs1use crate::Error;
2use quote::quote;
3
4pub fn generate(error: Error) -> proc_macro2::TokenStream {
5 let error_enum = &error.raw_enum;
6 let enum_name = &error.ident;
7 let display_variant_dispatch: Vec<proc_macro2::TokenStream> = error
10 .raw_enum
11 .variants
12 .iter()
13 .enumerate()
14 .map(|(idx, variant)| {
15 let ident = &variant.ident;
16 let error_code = &error.codes[idx];
17 let display_msg = match &error_code.msg {
18 None => {
19 quote! {
20 <Self as std::fmt::Debug>::fmt(self, fmt)
21 }
22 }
23 Some(msg) => {
24 quote! {
25 write!(fmt, #msg)
26 }
27 }
28 };
29 quote! {
30 #enum_name::#ident => #display_msg
31 }
32 })
33 .collect();
34
35 let name_variant_dispatch: Vec<proc_macro2::TokenStream> = error
38 .raw_enum
39 .variants
40 .iter()
41 .map(|variant| {
42 let ident = &variant.ident;
43 let ident_name = ident.to_string();
44 quote! {
45 #enum_name::#ident => #ident_name.to_string()
46 }
47 })
48 .collect();
49
50 let offset = match &error.args {
51 None => quote! { anchor_lang::error::ERROR_CODE_OFFSET},
52 Some(args) => {
53 let offset = &args.offset;
54 quote! { #offset }
55 }
56 };
57
58 let ret = quote! {
59 #[derive(std::fmt::Debug, Clone, Copy)]
60 #[repr(u32)]
61 #error_enum
62
63 impl #enum_name {
64 pub fn name(&self) -> String {
66 match self {
67 #(#name_variant_dispatch),*
68 }
69 }
70 }
71
72 impl From<#enum_name> for u32 {
73 fn from(e: #enum_name) -> u32 {
74 e as u32 + #offset
75 }
76 }
77
78 impl From<#enum_name> for anchor_lang::error::Error {
79 fn from(error_code: #enum_name) -> anchor_lang::error::Error {
80 anchor_lang::error::Error::from(
81 anchor_lang::error::AnchorError {
82 error_name: error_code.name(),
83 error_code_number: error_code.into(),
84 error_msg: error_code.to_string(),
85 error_origin: None,
86 compared_values: None
87 }
88 )
89 }
90 }
91
92 impl std::fmt::Display for #enum_name {
93 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
94 match self {
95 #(#display_variant_dispatch),*
96 }
97 }
98 }
99 };
100
101 #[cfg(feature = "idl-build")]
102 {
103 let idl_print = crate::idl::gen_idl_print_fn_error(&error);
104 return quote! {
105 #ret
106 #idl_print
107 };
108 };
109
110 #[allow(unreachable_code)]
111 ret
112}