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