-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
signature_derive: remove
synstructure
dependency (#1100)
It wasn't actually being used for anything structural, but rather for its higher-level proc macro API and testing facilities. However, both of those aren't too hard to replace, using `syn` for testing (via `parse_quote!`)
- Loading branch information
Showing
3 changed files
with
123 additions
and
104 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,4 +19,3 @@ proc-macro = true | |
proc-macro2 = "1" | ||
quote = "1" | ||
syn = "1" | ||
synstructure = "0.12.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,142 +1,163 @@ | ||
#![crate_type = "proc-macro"] | ||
#![doc = include_str!("../README.md")] | ||
#![deny(warnings, unused_import_braces, unused_qualifications)] | ||
#![forbid(unsafe_code)] | ||
#![warn( | ||
clippy::unwrap_used, | ||
rust_2018_idioms, | ||
trivial_casts, | ||
unused_import_braces, | ||
unused_qualifications | ||
)] | ||
|
||
extern crate proc_macro; | ||
|
||
use proc_macro2::TokenStream; | ||
use proc_macro::TokenStream; | ||
use proc_macro2::TokenStream as TokenStream2; | ||
use quote::quote; | ||
use synstructure::{decl_derive, AddBounds}; | ||
use syn::{parse_macro_input, DeriveInput}; | ||
|
||
/// Derive the [`Signer`] trait for a type which impls [`DigestSigner`]. | ||
/// | ||
/// When implementing the [`DigestSigner`] trait for a signature type which | ||
/// itself impl's the [`PrehashSignature`] trait (which marks signature | ||
/// algorithms which are computed using a [`Digest`]), signature providers | ||
/// can automatically derive the [`Signer`] trait when the digest algorithm | ||
/// is [`PrehashSignature::Digest`] (i.e. the "standard" digest algorithm | ||
/// for a given signature type) | ||
/// | ||
/// This automates all of the digest computation otherwise needed for a | ||
/// complete signature algorithm implementation. | ||
/// | ||
/// [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html | ||
/// [`DigestSigner`]: https://docs.rs/signature/latest/signature/trait.DigestSigner.html | ||
/// [`PrehashSignature`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html | ||
/// [`PrehashSignature::Digest`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html#associated-types | ||
#[proc_macro_derive(Signer)] | ||
pub fn derive_signer(input: TokenStream) -> TokenStream { | ||
let input = parse_macro_input!(input as DeriveInput); | ||
emit_signer_impl(input).into() | ||
} | ||
|
||
/// Derive the `Signer` trait for `DigestSigner` types | ||
fn derive_signer(mut s: synstructure::Structure) -> TokenStream { | ||
s.add_bounds(AddBounds::None); | ||
s.gen_impl(quote! { | ||
gen impl<S> signature::Signer<S> for @Self | ||
fn emit_signer_impl(input: DeriveInput) -> TokenStream2 { | ||
let ident = input.ident; | ||
let type_params = input.generics.type_params().collect::<Vec<_>>(); | ||
let type_idents = type_params | ||
.iter() | ||
.map(|bound| bound.ident.clone()) | ||
.collect::<Vec<_>>(); | ||
|
||
quote! { | ||
impl<S, #(#type_params),*> ::signature::Signer<S> for #ident<#(#type_idents),*> | ||
where | ||
S: signature::PrehashSignature, | ||
Self: signature::DigestSigner<S::Digest, S> | ||
S: ::signature::PrehashSignature, | ||
Self: ::signature::DigestSigner<S::Digest, S> | ||
{ | ||
fn try_sign(&self, msg: &[u8]) -> Result<S, signature::Error> { | ||
fn try_sign(&self, msg: &[u8]) -> Result<S, ::signature::Error> { | ||
self.try_sign_digest(S::Digest::new_with_prefix(msg)) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
decl_derive! { | ||
[Signer] => | ||
/// Derive the [`Signer`] trait for a type which impls [`DigestSigner`]. | ||
/// | ||
/// When implementing the [`DigestSigner`] trait for a signature type which | ||
/// itself impl's the [`PrehashSignature`] trait (which marks signature | ||
/// algorithms which are computed using a [`Digest`]), signature providers | ||
/// can automatically derive the [`Signer`] trait when the digest algorithm | ||
/// is [`PrehashSignature::Digest`] (i.e. the "standard" digest algorithm | ||
/// for a given signature type) | ||
/// | ||
/// This automates all of the digest computation otherwise needed for a | ||
/// complete signature algorithm implementation. | ||
/// | ||
/// [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html | ||
/// [`DigestSigner`]: https://docs.rs/signature/latest/signature/trait.DigestSigner.html | ||
/// [`PrehashSignature`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html | ||
/// [`PrehashSignature::Digest`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html#associated-types | ||
derive_signer | ||
/// Derive the [`Verifier`] trait for a type which impls [`DigestVerifier`]. | ||
/// | ||
/// When implementing the [`DigestVerifier`] trait for a signature type which | ||
/// itself impl's the [`PrehashSignature`] trait (which marks signature | ||
/// algorithms which are computed using a [`Digest`]), signature providers | ||
/// can automatically derive the [`Verifier`] trait when the digest algorithm | ||
/// is [`PrehashSignature::Digest`] (i.e. the "standard" digest algorithm | ||
/// for a given signature type) | ||
/// | ||
/// This automates all of the digest computation otherwise needed for a | ||
/// complete signature algorithm implementation. | ||
/// | ||
/// [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html | ||
/// [`DigestVerifier`]: https://docs.rs/signature/latest/signature/trait.DigestVerifier.html | ||
/// [`PrehashSignature`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html | ||
/// [`PrehashSignature::Digest`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html#associated-types | ||
#[proc_macro_derive(Verifier)] | ||
pub fn derive_verifier(input: TokenStream) -> TokenStream { | ||
let input = parse_macro_input!(input as DeriveInput); | ||
emit_verifier_impl(input).into() | ||
} | ||
|
||
/// Derive the `Verifier` trait for `DigestVerifier` types | ||
fn derive_verifier(mut s: synstructure::Structure) -> TokenStream { | ||
s.add_bounds(AddBounds::None); | ||
s.gen_impl(quote! { | ||
gen impl<S> signature::Verifier<S> for @Self | ||
fn emit_verifier_impl(input: DeriveInput) -> TokenStream2 { | ||
let ident = input.ident; | ||
let type_params = input.generics.type_params().collect::<Vec<_>>(); | ||
let type_idents = type_params | ||
.iter() | ||
.map(|bound| bound.ident.clone()) | ||
.collect::<Vec<_>>(); | ||
|
||
quote! { | ||
impl<S, #(#type_params),*> ::signature::Verifier<S> for #ident<#(#type_idents),*> | ||
where | ||
S: signature::PrehashSignature, | ||
Self: signature::DigestVerifier<S::Digest, S> | ||
S: ::signature::PrehashSignature, | ||
Self: ::signature::DigestVerifier<S::Digest, S> | ||
{ | ||
fn verify(&self, msg: &[u8], signature: &S) -> Result<(), signature::Error> { | ||
fn verify(&self, msg: &[u8], signature: &S) -> Result<(), ::signature::Error> { | ||
self.verify_digest(S::Digest::new_with_prefix(msg), signature) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
decl_derive! { | ||
[Verifier] => | ||
/// Derive the [`Verifier`] trait for a type which impls [`DigestVerifier`]. | ||
/// | ||
/// When implementing the [`DigestVerifier`] trait for a signature type which | ||
/// itself impl's the [`PrehashSignature`] trait (which marks signature | ||
/// algorithms which are computed using a [`Digest`]), signature providers | ||
/// can automatically derive the [`Verifier`] trait when the digest algorithm | ||
/// is [`PrehashSignature::Digest`] (i.e. the "standard" digest algorithm | ||
/// for a given signature type) | ||
/// | ||
/// This automates all of the digest computation otherwise needed for a | ||
/// complete signature algorithm implementation. | ||
/// | ||
/// [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html | ||
/// [`DigestVerifier`]: https://docs.rs/signature/latest/signature/trait.DigestVerifier.html | ||
/// [`PrehashSignature`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html | ||
/// [`PrehashSignature::Digest`]: https://docs.rs/signature/latest/signature/trait.PrehashSignature.html#associated-types | ||
derive_verifier | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use synstructure::test_derive; | ||
use syn::parse_quote; | ||
|
||
#[test] | ||
fn signer() { | ||
test_derive! { | ||
derive_signer { | ||
struct MySigner<C: EllipticCurve> { | ||
scalar: Scalar<C::ScalarSize> | ||
} | ||
let input = parse_quote! { | ||
#[derive(Signer)] | ||
struct MySigner<C: EllipticCurve> { | ||
scalar: Scalar<C::ScalarSize> | ||
} | ||
expands to { | ||
#[allow(non_upper_case_globals)] | ||
const _DERIVE_signature_Signer_S_FOR_MySigner: () = { | ||
impl<S, C: EllipticCurve> signature::Signer<S> for MySigner<C> | ||
where | ||
S: signature::PrehashSignature, | ||
Self: signature::DigestSigner<S::Digest, S> | ||
{ | ||
fn try_sign(&self, msg: &[u8]) -> Result <S, signature::Error> { | ||
self.try_sign_digest(S::Digest::new_with_prefix(msg)) | ||
} | ||
}; | ||
|
||
let output = emit_signer_impl(input); | ||
|
||
assert_eq!( | ||
output.to_string(), | ||
quote! { | ||
impl<S, C: EllipticCurve> ::signature::Signer<S> for MySigner<C> | ||
where | ||
S: ::signature::PrehashSignature, | ||
Self: ::signature::DigestSigner<S::Digest, S> | ||
{ | ||
fn try_sign(&self, msg: &[u8]) -> Result <S, ::signature::Error> { | ||
self.try_sign_digest(S::Digest::new_with_prefix(msg)) | ||
} | ||
}; | ||
} | ||
} | ||
no_build // tests in `signature-crate/tests` | ||
} | ||
.to_string() | ||
); | ||
} | ||
|
||
#[test] | ||
fn verifier() { | ||
test_derive! { | ||
derive_verifier { | ||
struct MyVerifier<C: EllipticCurve> { | ||
point: UncompressedPoint<C> | ||
} | ||
let input = parse_quote! { | ||
#[derive(Verifier)] | ||
struct MyVerifier<C: EllipticCurve> { | ||
point: UncompressedPoint<C> | ||
} | ||
expands to { | ||
#[allow(non_upper_case_globals)] | ||
const _DERIVE_signature_Verifier_S_FOR_MyVerifier: () = { | ||
impl<S, C: EllipticCurve> signature::Verifier<S> for MyVerifier<C> | ||
where | ||
S: signature::PrehashSignature, | ||
Self: signature::DigestVerifier<S::Digest, S> | ||
{ | ||
fn verify(&self, msg: &[u8], signature: &S) -> Result<(), signature::Error> { | ||
self.verify_digest(S::Digest::new_with_prefix(msg), signature) | ||
} | ||
}; | ||
|
||
let output = emit_verifier_impl(input); | ||
|
||
assert_eq!( | ||
output.to_string(), | ||
quote! { | ||
impl<S, C: EllipticCurve> ::signature::Verifier<S> for MyVerifier<C> | ||
where | ||
S: ::signature::PrehashSignature, | ||
Self: ::signature::DigestVerifier<S::Digest, S> | ||
{ | ||
fn verify(&self, msg: &[u8], signature: &S) -> Result<(), ::signature::Error> { | ||
self.verify_digest(S::Digest::new_with_prefix(msg), signature) | ||
} | ||
}; | ||
} | ||
} | ||
no_build // tests in `signature-crate/tests` | ||
} | ||
.to_string() | ||
); | ||
} | ||
} |