sessions_memory/
lib.rs

1use std::{
2    collections::HashMap,
3    io::{Error, ErrorKind, Result},
4    sync::{Arc, RwLock},
5    time::{Duration, Instant},
6};
7
8use sessions_core::{Data, Storage};
9
10#[derive(Debug, Clone)]
11pub struct State(Instant, Data);
12
13impl State {
14    fn new(i: Instant, d: Data) -> Self {
15        Self(i, d)
16    }
17}
18
19#[derive(Debug, Clone, Default)]
20pub struct MemoryStorage {
21    inner: Arc<RwLock<HashMap<String, State>>>,
22}
23
24impl MemoryStorage {
25    #[must_use]
26    pub fn new() -> Self {
27        Self::default()
28    }
29
30    /// Gets a reference to the underlying data.
31    #[must_use]
32    pub fn get_ref(&self) -> &RwLock<HashMap<String, State>> {
33        &self.inner
34    }
35}
36
37impl Storage for MemoryStorage {
38    async fn get(&self, key: &str) -> Result<Option<Data>> {
39        let state = self
40            .get_ref()
41            .read()
42            .map_err(into_io_error)?
43            .get(key)
44            .cloned();
45
46        if let Some(State(time, data)) = state {
47            if time >= Instant::now() {
48                return Ok(Some(data));
49            }
50            self.remove(key).await?;
51        }
52
53        Ok(None)
54    }
55
56    async fn set(&self, key: &str, val: Data, exp: &Duration) -> Result<()> {
57        self.get_ref()
58            .write()
59            .map_err(into_io_error)?
60            .insert(key.to_string(), State::new(Instant::now() + *exp, val));
61        Ok(())
62    }
63
64    async fn remove(&self, key: &str) -> Result<()> {
65        self.get_ref().write().map_err(into_io_error)?.remove(key);
66        Ok(())
67    }
68
69    async fn reset(&self) -> Result<()> {
70        self.get_ref().write().map_err(into_io_error)?.clear();
71        Ok(())
72    }
73}
74
75#[inline]
76fn into_io_error<E: std::error::Error>(e: E) -> Error {
77    Error::new(ErrorKind::Other, e.to_string())
78}