use std::fmt;
#[derive(Clone)]
pub struct SecureVault {
data: String,
}
impl SecureVault {
pub fn new<T: Into<String>>(data: T) -> Self {
Self { data: data.into() }
}
pub fn with_secure<F, T>(&self, f: F) -> T
where
F: FnOnce(&str) -> T,
{
f(&self.data)
}
pub fn with_secure_bytes<F, T>(&self, f: F) -> T
where
F: FnOnce(&[u8]) -> T,
{
f(self.data.as_bytes())
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl fmt::Debug for SecureVault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SecureVault(***)")
}
}
impl<T: Into<String>> From<T> for SecureVault {
fn from(data: T) -> Self {
Self::new(data)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProtectionLevel {
Basic,
Standard,
Maximum,
}
#[macro_export]
macro_rules! protect {
($($var:ident = $value:expr;)*) => {
$(
let $var = $crate::SecureVault::new($value);
)*
};
}
pub fn init() -> Result<(), &'static str> {
Ok(())
}
pub fn secure_cleanup() {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_protection() {
protect! {
let secret = "Hello, Secure World!";
}
let mut result = String::new();
secret.with_secure(|s| {
result = s.to_string();
});
assert_eq!(result, "Hello, Secure World!");
}
#[test]
fn test_multiple_secrets() {
protect! {
let secret1 = "first_secret";
let secret2 = "second_secret";
let secret3 = "third_secret";
}
secret1.with_secure(|s1| {
assert_eq!(*s1, "first_secret");
});
secret2.with_secure(|s2| {
assert_eq!(*s2, "second_secret");
});
secret3.with_secure(|s3| {
assert_eq!(*s3, "third_secret");
});
}
#[test]
fn test_bytes_access() {
protect! {
let secret = "secret_data";
}
secret.with_secure_bytes(|bytes| {
assert_eq!(bytes, b"secret_data");
});
}
#[test]
fn test_from_trait() {
let vault: SecureVault = "from_trait".into();
vault.with_secure(|data| {
assert_eq!(data, "from_trait");
});
}
#[test]
fn test_debug_format() {
let vault = SecureVault::new("secret");
let debug_output = format!("{:?}", vault);
assert_eq!(debug_output, "SecureVault(***)");
}
#[test]
fn test_len_and_empty() {
protect! {
let non_empty = "data";
let empty = "";
}
assert_eq!(non_empty.len(), 4);
assert!(!non_empty.is_empty());
assert_eq!(empty.len(), 0);
assert!(empty.is_empty());
}
}