From b76ff3aafd19263986f1c144c516bc72d715c62c Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 6 Aug 2024 16:13:30 -0700 Subject: [PATCH] signature_derive: adds support for lifetimes --- signature_derive/src/lib.rs | 66 +++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/signature_derive/src/lib.rs b/signature_derive/src/lib.rs index 14930789b..17ee1986c 100644 --- a/signature_derive/src/lib.rs +++ b/signature_derive/src/lib.rs @@ -14,8 +14,8 @@ use proc_macro::TokenStream; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{ - parse_macro_input, parse_quote, punctuated::Punctuated, DeriveInput, Ident, PredicateType, - Token, TraitBound, Type, TypeParam, TypeParamBound, WhereClause, WherePredicate, + parse_macro_input, parse_quote, punctuated::Punctuated, DeriveInput, Ident, Lifetime, + PredicateType, Token, TraitBound, Type, TypeParam, TypeParamBound, WhereClause, WherePredicate, }; /// Derive the [`Signer`] trait for a type which impls [`DigestSigner`]. @@ -51,12 +51,13 @@ fn emit_signer_impl(input: DeriveInput) -> TokenStream2 { ); let name = params.name; + let lifetimes = params.lifetimes; let impl_generics = params.impl_generics; let ty_generics = params.ty_generics; let where_clause = params.where_clause; quote! { - impl<#(#impl_generics),*> ::signature::Signer<#s_ident> for #name<#(#ty_generics),*> + impl<#(#lifetimes),*, #(#impl_generics),*> ::signature::Signer<#s_ident> for #name<#(#lifetimes),*, #(#ty_generics),*> #where_clause { fn try_sign(&self, msg: &[u8]) -> ::signature::Result<#s_ident> { @@ -99,12 +100,13 @@ fn emit_verifier_impl(input: DeriveInput) -> TokenStream2 { ); let name = params.name; + let lifetimes = params.lifetimes; let impl_generics = params.impl_generics; let ty_generics = params.ty_generics; let where_clause = params.where_clause; quote! { - impl<#(#impl_generics),*> ::signature::Verifier<#s_ident> for #name<#(#ty_generics),*> + impl<#(#lifetimes),*,#(#impl_generics),*> ::signature::Verifier<#s_ident> for #name<#(#lifetimes),*,#(#ty_generics),*> #where_clause { fn verify(&self, msg: &[u8], signature: &#s_ident) -> ::signature::Result<()> { @@ -137,12 +139,13 @@ fn emit_digest_signer_impl(input: DeriveInput) -> TokenStream2 { ); let name = params.name; + let lifetimes = params.lifetimes; let impl_generics = params.impl_generics; let ty_generics = params.ty_generics; let where_clause = params.where_clause; quote! { - impl<#(#impl_generics),*> ::signature::DigestSigner<#d_ident, #s_ident> for #name<#(#ty_generics),*> + impl<#(#lifetimes),*,#(#impl_generics),*> ::signature::DigestSigner<#d_ident, #s_ident> for #name<#(#lifetimes),*,#(#ty_generics),*> #where_clause { fn try_sign_digest(&self, digest: #d_ident) -> ::signature::Result<#s_ident> { @@ -175,12 +178,13 @@ fn emit_digest_verifier_impl(input: DeriveInput) -> TokenStream2 { ); let name = params.name; + let lifetimes = params.lifetimes; let impl_generics = params.impl_generics; let ty_generics = params.ty_generics; let where_clause = params.where_clause; quote! { - impl<#(#impl_generics),*> ::signature::DigestVerifier<#d_ident, #s_ident> for #name<#(#ty_generics),*> + impl<#(#lifetimes),*,#(#impl_generics),*> ::signature::DigestVerifier<#d_ident, #s_ident> for #name<#(#lifetimes),*,#(#ty_generics),*> #where_clause { fn verify_digest(&self, digest: #d_ident, signature: &#s_ident) -> ::signature::Result<()> { @@ -195,6 +199,8 @@ struct DeriveParams { /// Name of the struct the trait impls are being added to. name: Ident, + lifetimes: Vec, + /// Generic parameters of `impl`. impl_generics: Vec, @@ -210,6 +216,12 @@ impl DeriveParams { fn new(input: DeriveInput) -> Self { let impl_generics = input.generics.type_params().cloned().collect(); + let lifetimes = input + .generics + .lifetimes() + .map(|lt| lt.lifetime.clone()) + .collect(); + let ty_generics = input .generics .type_params() @@ -227,6 +239,7 @@ impl DeriveParams { Self { name: input.ident, + lifetimes, impl_generics, ty_generics, where_clause, @@ -291,7 +304,7 @@ mod tests { assert_eq!( output.to_string(), quote! { - impl ::signature::Signer<__S> for MySigner + impl<, C, __S> ::signature::Signer<__S> for MySigner<, C> where C: EllipticCurve, __S: ::signature::PrehashSignature, @@ -320,7 +333,7 @@ mod tests { assert_eq!( output.to_string(), quote! { - impl ::signature::Verifier<__S> for MyVerifier + impl<,C: EllipticCurve, __S> ::signature::Verifier<__S> for MyVerifier<,C> where __S: ::signature::PrehashSignature, Self: ::signature::DigestVerifier<__S::Digest, __S> @@ -348,7 +361,7 @@ mod tests { assert_eq!( output.to_string(), quote! { - impl ::signature::DigestSigner<__D, __S> for MySigner + impl<,C: EllipticCurve, __D, __S> ::signature::DigestSigner<__D, __S> for MySigner<,C> where __D: ::signature::digest::Digest, Self: ::signature::hazmat::PrehashSigner<__S> @@ -376,7 +389,7 @@ mod tests { assert_eq!( output.to_string(), quote! { - impl ::signature::DigestVerifier<__D, __S> for MyVerifier + impl<,C: EllipticCurve, __D, __S> ::signature::DigestVerifier<__D, __S> for MyVerifier<,C> where __D: ::signature::digest::Digest, Self: ::signature::hazmat::PrehashVerifier<__S> @@ -389,4 +402,37 @@ mod tests { .to_string() ); } + + #[test] + fn signer_lifetimes() { + let input = parse_quote! { + #[derive(Signer)] + struct MySigner<'a, C> + where + C: EllipticCurve + { + scalar: Scalar, + _lifetime: &'a (), + } + }; + + let output = emit_signer_impl(input); + + assert_eq!( + output.to_string(), + quote! { + impl<'a, C, __S> ::signature::Signer<__S> for MySigner<'a, C> + where + C: EllipticCurve, + __S: ::signature::PrehashSignature, + Self: ::signature::DigestSigner<__S::Digest, __S> + { + fn try_sign(&self, msg: &[u8]) -> ::signature::Result<__S> { + self.try_sign_digest(__S::Digest::new_with_prefix(msg)) + } + } + } + .to_string() + ); + } }