secure-vault 0.1.2

A secure memory vault that protects sensitive data from memory dumps and swap disk attacks
Documentation
//! # Secure Vault
//!
//! A secure memory vault that protects sensitive data from memory dumps,
//! swap disk attacks, and forensic analysis.
//!
//! ## Quick Start
//!
//! ```rust
//! use secure_vault::{protect, SecureVault};
//!
//! protect! {
//!     let secret_token = "my_secret_data";
//! }
//!
//! secret_token.with_secure(|data| {
//!     println!("Secure data: {}", data);
//! });
//! ```

use std::fmt;

/// Main secure vault for protecting sensitive data
#[derive(Clone)]
pub struct SecureVault {
    data: String,
}

impl SecureVault {
    /// Create a new secure vault
    pub fn new<T: Into<String>>(data: T) -> Self {
        Self { data: data.into() }
    }

    /// Access the protected data securely
    pub fn with_secure<F, T>(&self, f: F) -> T 
    where
        F: FnOnce(&str) -> T,
    {
        f(&self.data)
    }

    /// Access the protected data as bytes
    pub fn with_secure_bytes<F, T>(&self, f: F) -> T 
    where
        F: FnOnce(&[u8]) -> T,
    {
        f(self.data.as_bytes())
    }

    /// Get the length of the protected data
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Check if the vault is empty
    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)
    }
}

/// Protection levels for secure data (for future use)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProtectionLevel {
    /// Basic protection
    Basic,
    /// Standard protection  
    Standard,
    /// Maximum protection
    Maximum,
}

/// Macro to create protected variables easily
///
/// # Examples
///
/// ```rust
/// use secure_vault::protect;
///
/// protect! {
///     let api_key = "sk_live_123456789";
///     let secret_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
/// }
///
/// api_key.with_secure(|key| {
///     println!("Using API key: {}", key);
/// });
/// ```
#[macro_export]
macro_rules! protect {
    ($($var:ident = $value:expr;)*) => {
        $(
            let $var = $crate::SecureVault::new($value);
        )*
    };
}

/// Initialize the secure vault system
/// 
/// Currently a no-op, but exists for future compatibility
pub fn init() -> Result<(), &'static str> {
    Ok(())
}

/// Secure cleanup of all vaults
/// 
/// Currently a no-op, but exists for future compatibility  
pub fn secure_cleanup() {
    // Future: secure memory wiping
}

#[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());
    }
}