1use std::sync::Arc;
28
29use crate::error::Result;
30use crate::manager::EncryptionManager;
31
32#[derive(Debug, Clone)]
37pub struct Guard {
38 manager: Arc<EncryptionManager>,
39}
40
41impl Guard {
42 pub fn new(manager: EncryptionManager) -> Self {
44 Self {
45 manager: Arc::new(manager),
46 }
47 }
48
49 pub fn from_master_key(master_key: &[u8], default_identifier: &str) -> Result<Self> {
53 Ok(Self::new(
54 crate::factory::EncryptionManagerFactory::from_master_key(
55 master_key,
56 default_identifier,
57 )?,
58 ))
59 }
60
61 pub fn manager(&self) -> &EncryptionManager {
63 &self.manager
64 }
65
66 pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>> {
68 self.manager.encrypt(plaintext)
69 }
70
71 pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
73 self.manager.decrypt(ciphertext)
74 }
75
76 pub fn encrypt_with(&self, identifier: &str, plaintext: &[u8]) -> Result<Vec<u8>> {
78 self.manager.encrypt_with(identifier, plaintext)
79 }
80
81 pub fn decrypt_with(&self, identifier: &str, ciphertext: &[u8]) -> Result<Vec<u8>> {
83 self.manager.decrypt_with(identifier, ciphertext)
84 }
85
86 pub fn identifiers(&self) -> Vec<&str> {
88 self.manager.registry().identifiers()
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 fn guard() -> Guard {
97 Guard::from_master_key(&[7u8; 32], "aes-256-gcm").unwrap()
98 }
99
100 #[test]
101 fn wraps_the_factory_and_forwards() {
102 let guard = guard();
103 assert_eq!(guard.identifiers().len(), 5);
104 assert_eq!(guard.manager().default_identifier(), "aes-256-gcm");
105
106 let blob = guard.encrypt(b"phone").unwrap();
107 assert_eq!(guard.decrypt(&blob).unwrap(), b"phone");
108
109 let blob = guard.encrypt_with("sm4-cbc", b"phone").unwrap();
110 assert_eq!(guard.decrypt_with("sm4-cbc", &blob).unwrap(), b"phone");
111 }
112
113 #[test]
114 fn clones_share_one_manager() {
115 let guard = guard();
116 let clone = guard.clone();
117 let blob = guard.encrypt(b"shared").unwrap();
118 assert_eq!(clone.decrypt(&blob).unwrap(), b"shared");
119 assert_eq!(Arc::strong_count(&guard.manager), 2);
120 }
121
122 #[test]
123 fn invalid_master_key_fails_at_construction() {
124 assert!(Guard::from_master_key(&[0u8; 16], "aes-256-gcm").is_err());
125 assert!(Guard::from_master_key(&[0u8; 32], "no-such-algorithm").is_err());
126 }
127}