use zeroize::Zeroize;
#[derive(Clone)]
pub struct ZeroizingSecret<T: Zeroize + Clone>(T);
impl<T: Zeroize + Clone> ZeroizingSecret<T> {
pub fn new(inner: T) -> Self {
Self(inner)
}
pub fn get(&self) -> &T {
&self.0
}
pub fn expose(self) -> T {
let value = self.0.clone();
drop(self); value
}
pub fn map<U: Zeroize + Clone, F: FnOnce(&T) -> U>(self, f: F) -> ZeroizingSecret<U> {
let result = ZeroizingSecret::new(f(&self.0));
drop(self);
result
}
}
impl<T: Zeroize + Clone> AsRef<T> for ZeroizingSecret<T> {
fn as_ref(&self) -> &T {
&self.0
}
}
impl<T: Zeroize + Clone + Default> Default for ZeroizingSecret<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: Zeroize + Clone> Drop for ZeroizingSecret<T> {
fn drop(&mut self) {
self.0.zeroize();
}
}
impl<T: Zeroize + Clone + PartialEq> PartialEq for ZeroizingSecret<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T: Zeroize + Clone + core::fmt::Debug> core::fmt::Debug for ZeroizingSecret<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ZeroizingSecret")
.field("type", &std::any::type_name::<T>())
.finish()
}
}
pub type ZeroizingString = ZeroizingSecret<String>;
impl ZeroizingString {
#[must_use]
pub fn from_string(s: String) -> Self {
Self::new(s)
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}