megacommerce_shared_sanitize_derive/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput};
4
5#[proc_macro_derive(SanitizeAppError)]
6pub fn sanitize_app_error(input: TokenStream) -> TokenStream {
7  let input = parse_macro_input!(input as DeriveInput);
8  let name = input.ident;
9
10  // By convention we assume each response has a `response` oneof with an Error variant.
11  // Prost generates an enum called `<lowercase_struct_name>::Response`
12  // where one variant is `Error(AppError)`.
13  let mod_name =
14    syn::Ident::new(&format!("{}::response", name.to_string().to_lowercase()), name.span());
15  let enum_name = syn::Ident::new("Response", name.span());
16
17  let expanded = quote! {
18      impl SanitizeAppError for #name {
19          fn sanitize_app_error_fields(&mut self) {
20              if let Some(#mod_name::#enum_name::Error(err)) = self.response.take() {
21                  self.response =
22                      Some(#mod_name::#enum_name::Error(sanitize_app_error(&err)));
23              }
24          }
25      }
26  };
27
28  TokenStream::from(expanded)
29}