//! //! Structure describing secret. //! use std::{fmt, marker::PhantomData}; use crate::{strategy::Strategy, PeekInterface}; /// /// Secret thing. /// /// To get access to value use method `expose()` of trait [`crate::ExposeInterface`]. /// /// ## Masking /// Use the [`crate::strategy::Strategy`] trait to implement a masking strategy on a unit struct /// and pass the unit struct as a second generic parameter to [`Secret`] while defining it. /// [`Secret`] will take care of applying the masking strategy on the inner secret when being /// displayed. /// /// ## Masking Example /// /// ``` /// use masking::Strategy; /// use masking::Secret; /// use std::fmt; /// /// struct MyStrategy; /// /// impl Strategy for MyStrategy /// where /// T: fmt::Display /// { /// fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "{}", val.to_string().to_ascii_lowercase()) /// } /// } /// /// let my_secret: Secret = Secret::new("HELLO".to_string()); /// /// assert_eq!("hello", &format!("{:?}", my_secret)); /// ``` /// pub struct Secret where MaskingStrategy: Strategy, { pub(crate) inner_secret: Secret, pub(crate) masking_strategy: PhantomData, } impl Secret where MaskingStrategy: Strategy, { /// Take ownership of a secret value pub fn new(secret: SecretValue) -> Self { Self { inner_secret: secret, masking_strategy: PhantomData, } } } impl PeekInterface for Secret where MaskingStrategy: Strategy, { fn peek(&self) -> &SecretValue { &self.inner_secret } } impl From for Secret where MaskingStrategy: Strategy, { fn from(secret: SecretValue) -> Self { Self::new(secret) } } impl Clone for Secret where SecretValue: Clone, MaskingStrategy: Strategy, { fn clone(&self) -> Self { Self { inner_secret: self.inner_secret.clone(), masking_strategy: PhantomData, } } } impl PartialEq for Secret where Self: PeekInterface, SecretValue: PartialEq, MaskingStrategy: Strategy, { fn eq(&self, other: &Self) -> bool { self.peek().eq(other.peek()) } } impl Eq for Secret where Self: PeekInterface, SecretValue: Eq, MaskingStrategy: Strategy, { } impl fmt::Debug for Secret where MaskingStrategy: Strategy, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { MaskingStrategy::fmt(&self.inner_secret, f) } } impl Default for Secret where SecretValue: Default, MaskingStrategy: Strategy, { fn default() -> Self { SecretValue::default().into() } }