rivescript_core/sessions/
memory.rs1use std::collections::VecDeque;
2use std::{collections::HashMap, sync::RwLock};
3
4use async_trait::async_trait;
5
6use crate::sessions::{SessionManager, History};
7use crate::sessions::ThawAction::*;
8
9pub struct MemorySession {
10 users: RwLock<HashMap<String, UserData>>,
13}
14
15#[derive(Clone)]
16struct UserData {
17 vars: HashMap<String, String>,
18 frozen: HashMap<String, String>,
19 history_input: VecDeque<String>,
20 history_reply: VecDeque<String>,
21}
22
23impl UserData {
24 pub fn new() -> Self {
25 let mut input = VecDeque::with_capacity(crate::MAX_HISTORY);
26 let mut reply = VecDeque::with_capacity(crate::MAX_HISTORY);
27
28 for _ in 0..crate::MAX_HISTORY {
29 input.push_back(crate::UNDEFINED.to_string());
30 reply.push_back(crate::UNDEFINED.to_string());
31 }
32
33 Self {
34 vars: HashMap::new(),
35 frozen: HashMap::new(),
36 history_input: input,
37 history_reply: reply,
38 }
39 }
40}
41
42impl MemorySession {
43 pub fn new() -> Self {
44 Self {
45 users: RwLock::new(HashMap::new()),
46 }
47 }
48}
49
50#[async_trait]
51impl SessionManager for MemorySession {
52
53 async fn set(&self, username: &str, vars: HashMap<String, String>) {
54 let mut store = self.users.write().expect("RwLock poisoned");
55 let user_entry = store.entry(username.to_string()).or_insert_with(|| UserData::new());
56 user_entry.vars.extend(vars);
57 }
58
59 async fn add_history(&self, username: &str, input: &str, reply: &str) {
60 let mut store = self.users.write().expect("RwLock poisoned");
61 let user_entry = store.entry(username.to_string()).or_insert_with(|| UserData::new());
62
63 user_entry.history_input.pop_back();
65 user_entry.history_reply.pop_back();
66
67 user_entry.history_input.push_front(input.trim().to_string());
69 user_entry.history_reply.push_front(reply.trim().to_string());
70 }
71
72 async fn get_history(&self, username: &str) -> History {
73 let store = self.users.read().expect("RwLock poisoned");
74 store.get(username)
75 .map(|user_data| History {
76 input: user_data.history_input.iter().cloned().collect(),
77 reply: user_data.history_reply.iter().cloned().collect(),
78 }).unwrap_or_default()
79 }
80
81 async fn get(&self, username: &str, name: &str) -> String {
82 let store = self.users.read().expect("RwLock poisoned");
83 store.get(username)
84 .and_then(|user_data| user_data.vars.get(name))
85 .cloned()
86 .unwrap_or_else(|| crate::UNDEFINED.to_string())
87 }
88
89 async fn get_any(&self, username: &str) -> HashMap<String, String> {
90 let store = self.users.read().expect("RwLock poisoned");
91 store.get(username)
92 .map(|user_data| user_data.vars.clone())
93 .unwrap_or_else(|| HashMap::new())
94 }
95
96 async fn get_all(&self) -> HashMap<String, HashMap<String, String>> {
97 let store = self.users.read().expect("RwLock poisoned");
98 store.iter()
99 .map(|(username, data)| {
100 (username.clone(), data.vars.clone())
101 })
102 .collect()
103 }
104
105 async fn clear(&self, username: &str) {
106 let mut store = self.users.write().expect("RwLock poisoned");
107 store.remove(username);
108 }
109
110 async fn clear_all(&self) {
111 let mut store = self.users.write().expect("RwLock poisoned");
112 store.clear();
113 }
114
115 async fn freeze(&self, username: &str) -> Result<bool, String> {
116 let mut store = self.users.write().expect("RwLock poisoned");
117
118 if let Some(user_data) = store.get_mut(username) {
119 user_data.frozen.clear();
120 user_data.frozen = user_data.vars.clone();
121 } else {
122 return Err("no user data found".to_string());
123 }
124
125 Ok(true)
126 }
127
128 async fn thaw(&self, username: &str, action: crate::sessions::ThawAction) -> Result<bool, String> {
129 let mut store = self.users.write().expect("RwLock poisoned");
130
131 if let Some(user_data) = store.get_mut(username) {
132
133 match action {
135 Discard => {
136 user_data.frozen.clear();
137 }
138 Thaw | Keep => {
139 user_data.vars.clear();
140 user_data.vars = user_data.frozen.clone();
141
142 if !matches!(action, Keep) {
143 user_data.frozen.clear();
144 }
145 },
146 }
147
148 } else {
149 return Err("no user data found".to_string());
150 }
151
152 Ok(true)
153 }
154}