bee_common_derive/lib.rs
1// Copyright 2020 IOTA Stiftung
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4// the License. You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
9// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and limitations under the License.
11
12//! Derive macros for the bee-common crate.
13
14#![warn(missing_docs)]
15#![no_std]
16
17use quote::quote;
18use syn::{parse_macro_input, DeriveInput};
19
20/// Derives an implementation of the trait `core::fmt::Debug` for a secret type that doesn't leak its internal secret.
21/// Implements https://github.com/iotaledger/bee-rfcs/blob/master/text/0042-secret-debug-display.md.
22/// Based on https://github.com/dtolnay/syn/blob/master/examples/heapsize/heapsize_derive/src/lib.rs.
23#[proc_macro_derive(SecretDebug)]
24pub fn derive_secret_debug(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
25 // Parse the input tokens into a syntax tree.
26 let input = parse_macro_input!(input as DeriveInput);
27 // Used in the quasi-quotation below as `#name`.
28 let name = input.ident;
29 // Get the different implementation elements from the input.
30 let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
31
32 // The generated implementation.
33 let expanded = quote! {
34 impl #impl_generics core::fmt::Debug for #name #ty_generics {
35 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36 write!(f, "<Omitted secret>")
37 }
38 }
39 };
40
41 expanded.into()
42}
43
44/// Derives an implementation of the trait `core::fmt::Display` for a secret type that doesn't leak its internal secret.
45/// Implements https://github.com/iotaledger/bee-rfcs/blob/master/text/0042-secret-debug-display.md.
46/// Based on https://github.com/dtolnay/syn/blob/master/examples/heapsize/heapsize_derive/src/lib.rs.
47#[proc_macro_derive(SecretDisplay)]
48pub fn derive_secret_display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
49 // Parse the input tokens into a syntax tree.
50 let input = parse_macro_input!(input as DeriveInput);
51 // Used in the quasi-quotation below as `#name`.
52 let name = input.ident;
53 // Get the different implementation elements from the input.
54 let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
55
56 // The generated implementation.
57 let expanded = quote! {
58 impl #impl_generics core::fmt::Display for #name #ty_generics {
59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60 write!(f, "<Omitted secret>")
61 }
62 }
63 };
64
65 expanded.into()
66}
67
68/// Derives an implementation of the trait `core::ops::Drop` for a secret type that calls `Zeroize::zeroize`.
69/// Implements https://github.com/iotaledger/bee-rfcs/blob/master/text/0044-secret-zeroize-drop.md.
70/// Based on https://github.com/dtolnay/syn/blob/master/examples/heapsize/heapsize_derive/src/lib.rs.
71#[proc_macro_derive(SecretDrop)]
72pub fn derive_secret_drop(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
73 // Parse the input tokens into a syntax tree.
74 let input = parse_macro_input!(input as DeriveInput);
75 // Used in the quasi-quotation below as `#name`.
76 let name = input.ident;
77 // Get the different implementation elements from the input.
78 let (impl_generics, ty_generics, _) = input.generics.split_for_impl();
79
80 // The generated implementation.
81 let expanded = quote! {
82 impl #impl_generics core::ops::Drop for #name #ty_generics {
83 fn drop(&mut self) {
84 self.zeroize()
85 }
86 }
87 };
88
89 expanded.into()
90}