use core::fmt;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{Ordering, compiler_fence};
use super::assert::assert_zeroize_on_drop;
use super::traits::{AssertZeroizeOnDrop, FastZeroizable, ZeroizationProbe};
use super::zeroize_on_drop_sentinel::ZeroizeOnDropSentinel;
pub struct ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
inner: &'a mut T,
__sentinel: ZeroizeOnDropSentinel,
}
impl<'a, T> fmt::Debug for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[REDACTED ZeroizingMutGuard]")
}
}
impl<'a, T> ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
pub fn from(inner: &'a mut T) -> Self {
Self {
inner,
__sentinel: ZeroizeOnDropSentinel::default(),
}
}
}
impl<'a, T> Deref for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner
}
}
impl<'a, T> DerefMut for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner
}
}
impl<'a, T> FastZeroizable for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
fn fast_zeroize(&mut self) {
self.inner.fast_zeroize();
compiler_fence(Ordering::SeqCst);
self.__sentinel.fast_zeroize();
compiler_fence(Ordering::SeqCst);
}
}
impl<'a, T> AssertZeroizeOnDrop for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
fn clone_sentinel(&self) -> ZeroizeOnDropSentinel {
self.__sentinel.clone()
}
fn assert_zeroize_on_drop(self) {
assert_zeroize_on_drop(self);
}
}
impl<'a, T> ZeroizationProbe for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
fn is_zeroized(&self) -> bool {
self.inner.is_zeroized()
}
}
impl<'a, T> Drop for ZeroizingMutGuard<'a, T>
where
T: FastZeroizable + ZeroizationProbe + ?Sized,
{
fn drop(&mut self) {
self.fast_zeroize();
}
}