use crate::ffi;
use std::ops::Deref;
pub struct SecretString {
inner: String,
}
impl SecretString {
pub fn new(s: String) -> Self {
SecretString { inner: s }
}
#[allow(clippy::should_implement_trait)]
pub fn from_str(s: &str) -> Self {
Self::new(s.to_owned())
}
pub fn as_str(&self) -> &str {
&self.inner
}
pub fn into_string(self) -> String {
let me = std::mem::ManuallyDrop::new(self);
unsafe { std::ptr::read(&me.inner) }
}
pub fn zeroize(&mut self) {
zero_string_bytes(&mut self.inner);
}
}
impl Drop for SecretString {
fn drop(&mut self) {
self.zeroize();
}
}
impl Deref for SecretString {
type Target = str;
fn deref(&self) -> &str {
&self.inner
}
}
impl AsRef<str> for SecretString {
fn as_ref(&self) -> &str {
&self.inner
}
}
impl From<String> for SecretString {
fn from(s: String) -> Self {
SecretString::new(s)
}
}
impl std::fmt::Debug for SecretString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("SecretString(***)")
}
}
pub fn zero_string_bytes(s: &mut str) {
unsafe {
let bytes = s.as_bytes_mut();
let ptr = bytes.as_mut_ptr() as *mut std::ffi::c_void;
ffi::rnp_buffer_clear(ptr, bytes.len());
}
}