use serde::{Serialize, de::DeserializeOwned};
use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock;
pub type SessionId = String;
#[derive(Debug, Clone)]
pub struct Session {
id: SessionId,
data: Arc<RwLock<HashMap<String, serde_json::Value>>>,
dirty: Arc<RwLock<bool>>,
is_new: bool,
}
impl Session {
pub fn new(id: impl Into<String>) -> Self {
Self { id: id.into(), data: Arc::new(RwLock::new(HashMap::new())), dirty: Arc::new(RwLock::new(false)), is_new: true }
}
pub async fn from_data(id: impl Into<String>, data: HashMap<String, serde_json::Value>) -> Self {
Self { id: id.into(), data: Arc::new(RwLock::new(data)), dirty: Arc::new(RwLock::new(false)), is_new: false }
}
pub fn id(&self) -> &str {
&self.id
}
pub fn is_new(&self) -> bool {
self.is_new
}
pub async fn is_dirty(&self) -> bool {
*self.dirty.read().await
}
pub async fn mark_dirty(&self) {
*self.dirty.write().await = true;
}
pub async fn get(&self, key: &str) -> Option<serde_json::Value> {
self.data.read().await.get(key).cloned()
}
pub async fn get_typed<T: DeserializeOwned>(&self, key: &str) -> Option<T> {
self.data.read().await.get(key).and_then(|v| serde_json::from_value(v.clone()).ok())
}
pub async fn set<T: Serialize>(&self, key: impl Into<String>, value: T) {
let key = key.into();
let json_value = serde_json::to_value(value).unwrap_or(serde_json::Value::Null);
self.data.write().await.insert(key, json_value);
*self.dirty.write().await = true;
}
pub async fn remove(&self, key: &str) -> Option<serde_json::Value> {
let result = self.data.write().await.remove(key);
if result.is_some() {
*self.dirty.write().await = true;
}
result
}
pub async fn contains(&self, key: &str) -> bool {
self.data.read().await.contains_key(key)
}
pub async fn clear(&self) {
self.data.write().await.clear();
*self.dirty.write().await = true;
}
pub async fn keys(&self) -> Vec<String> {
self.data.read().await.keys().cloned().collect()
}
pub async fn len(&self) -> usize {
self.data.read().await.len()
}
pub async fn is_empty(&self) -> bool {
self.data.read().await.is_empty()
}
pub async fn to_json(&self) -> String {
let data = self.data.read().await;
serde_json::to_string(&*data).unwrap_or_default()
}
pub async fn from_json(&self, json: &str) -> bool {
if let Ok(data) = serde_json::from_str::<HashMap<String, serde_json::Value>>(json) {
*self.data.write().await = data;
true
}
else {
false
}
}
}