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 #[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}