use crate::core::Session;
use crate::error::Result;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
pub trait SessionStore: Send + Sync {
fn save(&self, session: &Session) -> Result<()>;
fn load(&self) -> Result<Option<Session>>;
fn delete(&self) -> Result<()>;
}
#[derive(Debug)]
pub struct FileSessionStore {
path: PathBuf,
}
impl FileSessionStore {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
Self {
path: path.as_ref().to_path_buf(),
}
}
}
impl SessionStore for FileSessionStore {
fn save(&self, session: &Session) -> Result<()> {
let json = serde_json::to_string(session).map_err(|e| crate::SupaError::ClientError {
message: format!("Failed to serialize session: {}", e),
})?;
if let Some(parent) = self.path.parent() {
fs::create_dir_all(parent).map_err(|e| crate::SupaError::ClientError {
message: format!("Failed to create session dir: {}", e),
})?;
}
fs::write(&self.path, json).map_err(|e| crate::SupaError::ClientError {
message: format!("Failed to write session file: {}", e),
})?;
Ok(())
}
fn load(&self) -> Result<Option<Session>> {
if !self.path.exists() {
return Ok(None);
}
let json = fs::read_to_string(&self.path).map_err(|e| crate::SupaError::ClientError {
message: format!("Failed to read session file: {}", e),
})?;
let session: Session =
serde_json::from_str(&json).map_err(|e| crate::SupaError::ClientError {
message: format!("Failed to deserialize session: {}", e),
})?;
Ok(Some(session))
}
fn delete(&self) -> Result<()> {
if self.path.exists() {
fs::remove_file(&self.path).map_err(|e| crate::SupaError::ClientError {
message: format!("Failed to delete session file: {}", e),
})?;
}
Ok(())
}
}
#[derive(Debug, Default)]
pub struct MemorySessionStore {
session: Arc<Mutex<Option<Session>>>,
}
impl MemorySessionStore {
pub fn new() -> Self {
Self {
session: Arc::new(Mutex::new(None)),
}
}
}
impl SessionStore for MemorySessionStore {
fn save(&self, session: &Session) -> Result<()> {
let mut lock = self.session.lock().unwrap();
*lock = Some(session.clone());
Ok(())
}
fn load(&self) -> Result<Option<Session>> {
let lock = self.session.lock().unwrap();
Ok(lock.clone())
}
fn delete(&self) -> Result<()> {
let mut lock = self.session.lock().unwrap();
*lock = None;
Ok(())
}
}