beam/sea/session/
memory.rs1use super::super::{KeyPair, SeaError, SessionStorage};
14use async_trait::async_trait;
15use std::collections::HashMap;
16use std::sync::Mutex;
17
18pub struct InMemorySessionStorage {
22 data: Mutex<HashMap<String, KeyPair>>,
23}
24
25impl Default for InMemorySessionStorage {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl InMemorySessionStorage {
32 pub fn new() -> Self {
34 Self {
35 data: Mutex::new(HashMap::new()),
36 }
37 }
38}
39
40#[async_trait]
41impl SessionStorage for InMemorySessionStorage {
42 async fn save(&self, alias: &str, pair: &KeyPair) -> Result<(), SeaError> {
43 self.data
44 .lock()
45 .unwrap()
46 .insert(alias.to_string(), pair.clone());
47 Ok(())
48 }
49
50 async fn load(&self, alias: &str) -> Result<Option<KeyPair>, SeaError> {
51 Ok(self.data.lock().unwrap().get(alias).cloned())
52 }
53
54 async fn clear(&self, alias: &str) -> Result<(), SeaError> {
55 self.data.lock().unwrap().remove(alias);
56 Ok(())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 fn test_pair() -> KeyPair {
65 KeyPair {
66 pub_key: "test.pub".to_string(),
67 priv_key: "test.priv".to_string(),
68 epub_key: Some("test.epub".to_string()),
69 epriv_key: Some("test.epriv".to_string()),
70 }
71 }
72
73 #[tokio::test]
74 async fn test_save_load_roundtrip() {
75 let storage = InMemorySessionStorage::new();
76 let pair = test_pair();
77 storage.save("alice", &pair).await.unwrap();
78 let loaded = storage.load("alice").await.unwrap();
79 assert!(loaded.is_some());
80 let loaded = loaded.unwrap();
81 assert_eq!(loaded.pub_key, pair.pub_key);
82 assert_eq!(loaded.priv_key, pair.priv_key);
83 }
84
85 #[tokio::test]
86 async fn test_load_missing_returns_none() {
87 let storage = InMemorySessionStorage::new();
88 let loaded = storage.load("nobody").await.unwrap();
89 assert!(loaded.is_none());
90 }
91
92 #[tokio::test]
93 async fn test_clear_removes_entry() {
94 let storage = InMemorySessionStorage::new();
95 let pair = test_pair();
96 storage.save("bob", &pair).await.unwrap();
97 assert!(storage.load("bob").await.unwrap().is_some());
98 storage.clear("bob").await.unwrap();
99 assert!(storage.load("bob").await.unwrap().is_none());
100 }
101
102 #[tokio::test]
103 async fn test_default_is_empty() {
104 let storage = InMemorySessionStorage::default();
105 let loaded = storage.load("anyone").await.unwrap();
106 assert!(loaded.is_none());
107 }
108
109 #[tokio::test]
110 async fn test_overwrite_existing() {
111 let storage = InMemorySessionStorage::new();
112 let pair1 = test_pair();
113 let mut pair2 = test_pair();
114 pair2.pub_key = "other.pub".to_string();
115 storage.save("alice", &pair1).await.unwrap();
116 storage.save("alice", &pair2).await.unwrap();
117 let loaded = storage.load("alice").await.unwrap().unwrap();
118 assert_eq!(loaded.pub_key, "other.pub");
119 }
120}