securefmt 0.1.5

Drop-in replacement for the Debug derive macro that hides fields marked as sensitive.
Documentation
use super::{FormattingData, FormattingDataSource};
use crate::{
    errors::Result,
    formatting_data::{FieldFormattingData, VariantFormattingData},
};
use syn::{punctuated::Iter, Data, Fields, Variant};

impl FormattingDataSource for Data {
    fn to_formatting_data(&self) -> Result<FormattingData> {
        match self {
            Data::Struct(data) => Ok(FormattingData::StructData(extract_field_formatting_data(
                &data.fields,
            ))),
            Data::Enum(data) => Ok(FormattingData::EnumData(extract_variant_formatting_data(
                data.variants.iter(),
            ))),
            Data::Union(data) => secure_fmt_error!(
                data.union_token.span,
                "deriving secured Debug is not supported for unions"
            ),
        }
    }
}

fn extract_variant_formatting_data(variants: Iter<Variant>) -> Vec<VariantFormattingData> {
    variants
        .map(|v| VariantFormattingData {
            ident: v.ident.to_string(),
            fields: extract_field_formatting_data(&v.fields),
        })
        .collect()
}

fn extract_field_formatting_data(fields: &Fields) -> Vec<FieldFormattingData> {
    fields.iter().map(std::convert::Into::into).collect()
}

#[cfg(test)]
mod tests {
    use crate::formatting_data::{
        FieldFormattingData, FormattingData, FormattingDataSource, VariantFormattingData,
    };
    use pretty_assertions::assert_eq;
    use syn::DeriveInput;

    #[test]
    fn should_extract_formatting_data_for_struct() {
        let input: DeriveInput = syn::parse_quote! { struct SomeStruct { a: u8 } };
        let format_data = input
            .data
            .to_formatting_data()
            .expect("Should have succeeded");

        assert_eq!(
            format_data,
            FormattingData::StructData(vec![FieldFormattingData {
                ident: Some("a".to_string()),
                sensitive: false,
            }])
        );
    }

    #[test]
    fn should_extract_formatting_data_for_enum() {
        let input: DeriveInput = syn::parse_quote! { enum SomeEnum { A(u8) } };
        let format_data = input
            .data
            .to_formatting_data()
            .expect("Should have succeeded");

        assert_eq!(
            format_data,
            FormattingData::EnumData(vec![VariantFormattingData {
                ident: "A".to_string(),
                fields: vec![FieldFormattingData {
                    ident: None,
                    sensitive: false
                }],
            }])
        );
    }

    #[test]
    fn should_fail_to_extract_fields_for_union() {
        let input: DeriveInput = syn::parse_quote! { union SomeUnion {} };
        let err = input
            .data
            .to_formatting_data()
            .expect_err("Should have errored");

        assert_eq!(
            err.message,
            "deriving secured Debug is not supported for unions"
        );
    }
}