1use std::fmt;
21
22#[derive(Clone)]
24pub struct SecureVault {
25 data: String,
26}
27
28impl SecureVault {
29 pub fn new<T: Into<String>>(data: T) -> Self {
31 Self { data: data.into() }
32 }
33
34 pub fn with_secure<F, T>(&self, f: F) -> T
36 where
37 F: FnOnce(&str) -> T,
38 {
39 f(&self.data)
40 }
41
42 pub fn with_secure_bytes<F, T>(&self, f: F) -> T
44 where
45 F: FnOnce(&[u8]) -> T,
46 {
47 f(self.data.as_bytes())
48 }
49
50 pub fn len(&self) -> usize {
52 self.data.len()
53 }
54
55 pub fn is_empty(&self) -> bool {
57 self.data.is_empty()
58 }
59}
60
61impl fmt::Debug for SecureVault {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 write!(f, "SecureVault(***)")
64 }
65}
66
67impl<T: Into<String>> From<T> for SecureVault {
68 fn from(data: T) -> Self {
69 Self::new(data)
70 }
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum ProtectionLevel {
76 Basic,
78 Standard,
80 Maximum,
82}
83
84#[macro_export]
101macro_rules! protect {
102 ($($var:ident = $value:expr;)*) => {
103 $(
104 let $var = $crate::SecureVault::new($value);
105 )*
106 };
107}
108
109pub fn init() -> Result<(), &'static str> {
113 Ok(())
114}
115
116pub fn secure_cleanup() {
120 }
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_basic_protection() {
129 protect! {
130 let secret = "Hello, Secure World!";
131 }
132
133 let mut result = String::new();
134 secret.with_secure(|s| {
135 result = s.to_string();
136 });
137
138 assert_eq!(result, "Hello, Secure World!");
139 }
140
141 #[test]
142 fn test_multiple_secrets() {
143 protect! {
144 let secret1 = "first_secret";
145 let secret2 = "second_secret";
146 let secret3 = "third_secret";
147 }
148
149 secret1.with_secure(|s1| {
150 assert_eq!(*s1, "first_secret");
151 });
152
153 secret2.with_secure(|s2| {
154 assert_eq!(*s2, "second_secret");
155 });
156
157 secret3.with_secure(|s3| {
158 assert_eq!(*s3, "third_secret");
159 });
160 }
161
162 #[test]
163 fn test_bytes_access() {
164 protect! {
165 let secret = "secret_data";
166 }
167
168 secret.with_secure_bytes(|bytes| {
169 assert_eq!(bytes, b"secret_data");
170 });
171 }
172
173 #[test]
174 fn test_from_trait() {
175 let vault: SecureVault = "from_trait".into();
176
177 vault.with_secure(|data| {
178 assert_eq!(data, "from_trait");
179 });
180 }
181
182 #[test]
183 fn test_debug_format() {
184 let vault = SecureVault::new("secret");
185 let debug_output = format!("{:?}", vault);
186
187 assert_eq!(debug_output, "SecureVault(***)");
188 }
189
190 #[test]
191 fn test_len_and_empty() {
192 protect! {
193 let non_empty = "data";
194 let empty = "";
195 }
196
197 assert_eq!(non_empty.len(), 4);
198 assert!(!non_empty.is_empty());
199
200 assert_eq!(empty.len(), 0);
201 assert!(empty.is_empty());
202 }
203}