pub use zeroize::Zeroizing;
use std::cell::Cell;
pub struct ReadOnce<T: zeroize::Zeroize> {
inner: Option<T>,
taken: Cell<bool>,
}
impl<T: zeroize::Zeroize> ReadOnce<T> {
#[must_use]
pub fn new(value: T) -> Self {
Self {
inner: Some(value),
taken: Cell::new(false),
}
}
pub fn take(&mut self) -> Option<T> {
if self.taken.get() {
return None;
}
self.taken.set(true);
self.inner.take()
}
}
impl<T: zeroize::Zeroize> Drop for ReadOnce<T> {
fn drop(&mut self) {
if let Some(mut value) = self.inner.take() {
value.zeroize();
}
}
}
impl<T: zeroize::Zeroize + std::fmt::Debug> std::fmt::Debug for ReadOnce<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.taken.get() {
write!(f, "ReadOnce(<consumed>)")
} else {
write!(f, "ReadOnce(<available>)")
}
}
}