securefmt/
lib.rs

1#![deny(missing_docs)]
2//! Drop-in replacement for the Debug derive macro that hides fields marked as sensitive.
3//!
4//! # Example
5//! The following code snippet
6//! ```rust
7//! # extern crate securefmt;
8//! # use securefmt::Debug;
9//!
10//! #[derive(Debug)]
11//! struct SensitiveData {
12//!     id: u8,
13//!     #[sensitive]
14//!     secret: u8
15//! }
16//!
17//! fn main() {
18//!     println!("{:?}", SensitiveData { id: 1, secret: 42 })
19//! }
20//! ```
21//! will print:
22//! ```output
23//! SensitiveData { id: 1, secret: <redacted> }
24//! ```
25//!
26//! If the `debug_mode` feature is active, the same code will print:
27//! ```output
28//! WARN - WARNING: securefmt debug_mode feature is active. Sensitive data may be leaked. It is strongly recommended to disable debug_mode in production releases.
29//! SensitiveData { id: 1, secret: 42 }
30//! ```
31
32// use features::CompileTimeFeatureDiscriminator;
33use proc_macro::TokenStream;
34use syn::{parse_macro_input, DeriveInput};
35// use crate::implementation::SynDebugImplGenerator;
36
37#[macro_use]
38mod errors;
39mod derive;
40mod formatting_data;
41mod implementation;
42
43extern crate proc_macro;
44
45/// # Usage
46/// ```rust
47/// # extern crate securefmt;
48/// # use securefmt::Debug;
49/// #[derive(Debug)]
50/// struct SensitiveData {
51///     id: u8,
52///     #[sensitive]
53///     secret: u8
54/// }
55/// ```
56#[proc_macro_derive(Debug, attributes(sensitive))]
57pub fn derive_secure_debug(input: TokenStream) -> TokenStream {
58    let derive_input = parse_macro_input!(input as DeriveInput);
59    let derive_result = derive::debug(&derive_input.ident, &derive_input.data);
60
61    match derive_result {
62        Ok(tokens) => tokens.into(),
63        Err(e) => {
64            let syn_error = syn::Error::new(e.call_site, e.message);
65            let compile_error = syn_error.to_compile_error();
66            quote::quote! {
67                #compile_error
68            }
69            .into()
70        }
71    }
72}