asn1_rs_derive/
tostatic.rs1use proc_macro2::Span;
2use quote::quote;
3use syn::{Ident, Lifetime};
4
5pub fn derive_tostatic(s: synstructure::Structure) -> proc_macro2::TokenStream {
6 let ast = s.ast();
7
8 let debug_derive = ast.attrs.iter().any(|attr| {
9 attr.meta
10 .path()
11 .is_ident(&Ident::new("debug_derive", Span::call_site()))
12 });
13
14 let body = s.each_variant(|vi| {
17 let instrs = vi
19 .bindings()
20 .iter()
21 .enumerate()
22 .fold(quote! {}, |acc, (idx, bi)| {
23 let ident = Ident::new(&format!("_{idx}"), Span::call_site());
24 quote! { #acc let #ident = #bi.to_static(); }
25 });
26 let c = vi.construct(|_f, i| {
28 let ident = Ident::new(&format!("_{i}"), Span::call_site());
29 quote! { #ident }
30 });
31 quote! { #instrs #c }
32 });
33
34 let struct_ident = &ast.ident;
35
36 let static_token = match ast.generics.lifetimes().count() {
38 0 => None,
39 1 => {
40 let lt = Lifetime::new("'static", Span::call_site());
41 Some(quote! {<#lt>})
42 }
43 _ => {
44 let lt_static = Lifetime::new("'static", Span::call_site());
45 let lts = ast.generics.lifetimes().map(|_| lt_static.clone());
46 Some(quote! {<#(#lts),*>})
47 }
48 };
49
50 let ts = s.gen_impl(quote! {
51 gen impl asn1_rs::ToStatic for @Self {
52 type Owned = #struct_ident #static_token;
53
54 fn to_static(&self) -> Self::Owned {
55 match *self {
56 #body
57 }
58 }
59 }
60 });
61 if debug_derive {
62 eprintln!("TS: {ts}");
63 }
64 ts
65}