fastcrypto_derive/
lib.rs

1// Copyright (c) 2022, Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3#![warn(missing_docs, unreachable_pub)]
4
5//! This crate contains the `SilentDebug` and `SilentDisplay` derive macros.
6//! which help to avoid accidentally printing sensitive data.
7//! Imported from diem-crypto-derive@0.0.3
8//! https://github.com/diem/diem/blob/release-1.4.3/crypto/crypto-derive/src/lib.rs#L113
9
10use proc_macro::TokenStream;
11use quote::quote;
12use syn::DeriveInput;
13
14/// Derive the `SilentDisplay` trait, which is an implementation of `Display` that does not print the contents of the struct.
15/// This is useful for structs that contain sensitive data, such as private keys.
16#[proc_macro_derive(SilentDisplay)]
17pub fn silent_display(source: TokenStream) -> TokenStream {
18    let ast: DeriveInput = syn::parse(source).expect("Incorrect macro input");
19    let name = &ast.ident;
20    let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
21    let gen = quote! {
22        // In order to ensure that secrets are never leaked, Display is elided
23        impl #impl_generics ::std::fmt::Display for #name #type_generics #where_clause {
24            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
25                write!(f, "<elided secret for {}>", stringify!(#name))
26            }
27        }
28    };
29    gen.into()
30}
31
32#[proc_macro_derive(SilentDebug)]
33/// Derive the `SilentDebug` trait, which is an implementation of `Debug` that does not print the contents of the struct.
34/// This is useful for structs that contain sensitive data, such as private keys.
35pub fn silent_debug(source: TokenStream) -> TokenStream {
36    let ast: DeriveInput = syn::parse(source).expect("Incorrect macro input");
37    let name = &ast.ident;
38    let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
39    let gen = quote! {
40        // In order to ensure that secrets are never leaked, Debug is elided
41        impl #impl_generics ::std::fmt::Debug for #name #type_generics #where_clause {
42            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
43                write!(f, "<elided secret for {}>", stringify!(#name))
44            }
45        }
46    };
47    gen.into()
48}
49
50/// Extend implementations of Add, Sub, Mul<GroupElement::ScalarType> and Neg into implementations of
51/// Add, Sub, Neg, AddAssign, SubAssign and MulAssign for all combinations of borrowed and owned inputs.
52#[proc_macro_derive(GroupOpsExtend)]
53pub fn group_ops(source: TokenStream) -> TokenStream {
54    let ast: DeriveInput = syn::parse(source).expect("Incorrect macro input");
55    let name = &ast.ident;
56
57    let gen = quote! {
58
59        // Implement all combinations of borrowed and owned inputs assuming we have implemented the
60        // Add, Sub, Neg and Mul<GroupElement::ScalarType> for the given type.
61
62        auto_ops::impl_op!(+ |a: &#name, b: &#name| -> #name { <#name as core::ops::Add>::add(*a, *b) });
63        auto_ops::impl_op!(+ |a: &#name, b: #name| -> #name { <#name as core::ops::Add>::add(*a, b) });
64        auto_ops::impl_op!(+ |a: #name, b: &#name| -> #name { <#name as core::ops::Add>::add(a, *b) });
65
66        auto_ops::impl_op!(- |a: &#name, b: &#name| -> #name { <#name as core::ops::Sub>::sub(*a, *b) });
67        auto_ops::impl_op!(- |a: &#name, b: #name| -> #name { <#name as core::ops::Sub>::sub(*a, b) });
68        auto_ops::impl_op!(- |a: #name, b: &#name| -> #name { <#name as core::ops::Sub>::sub(a, *b) });
69
70        auto_ops::impl_op_ex!(+= |a: &mut #name, b: &#name| { *a = <#name as core::ops::Add>::add(*a, *b) });
71        auto_ops::impl_op_ex!(-= |a: &mut #name, b: &#name| { *a = <#name as core::ops::Sub>::sub(*a, *b) });
72        auto_ops::impl_op_ex!(*= |a: &mut #name, b: &<#name as GroupElement>::ScalarType| { *a = <#name as core::ops::Mul<<#name as GroupElement>::ScalarType>>::mul(*a, *b) });
73
74        auto_ops::impl_op!(* |a: &#name, b: &<#name as GroupElement>::ScalarType| -> #name { <#name as core::ops::Mul<<#name as GroupElement>::ScalarType>>::mul(*a, *b) });
75        auto_ops::impl_op!(* |a: &#name, b: <#name as GroupElement>::ScalarType| -> #name { <#name as core::ops::Mul<<#name as GroupElement>::ScalarType>>::mul(*a, b) });
76        auto_ops::impl_op!(* |a: #name, b: &<#name as GroupElement>::ScalarType| -> #name { <#name as core::ops::Mul<<#name as GroupElement>::ScalarType>>::mul(a, *b) });
77
78        auto_ops::impl_op!(- |a: &#name| -> #name { <#name as core::ops::Neg>::neg(*a) });
79    };
80    gen.into()
81}