1#![deny(missing_docs, missing_debug_implementations)]
8
9use serde::{Deserialize, Serialize};
10use wasm_bindgen::prelude::*;
11
12use crate::errors::js_to_error;
13use errors::StorageError;
14use serde_json::{Map, Value};
15
16pub mod errors;
17mod local_storage;
18mod session_storage;
19pub use local_storage::LocalStorage;
20pub use session_storage::SessionStorage;
21
22pub type Result<T> = std::result::Result<T, StorageError>;
24
25pub trait Storage {
27 fn raw() -> web_sys::Storage;
29
30 fn get<T>(key: impl AsRef<str>) -> Result<T>
32 where
33 T: for<'de> Deserialize<'de>,
34 {
35 let key = key.as_ref();
36 let item = Self::raw()
37 .get_item(key)
38 .expect_throw("unreachable: get_item does not throw an exception")
39 .ok_or_else(|| StorageError::KeyNotFound(key.to_string()))?;
40 let item = serde_json::from_str(&item)?;
41 Ok(item)
42 }
43
44 fn get_all<T>() -> Result<T>
46 where
47 T: for<'a> Deserialize<'a>,
48 {
49 let local_storage = Self::raw();
50 let length = Self::length();
51 let mut map = Map::with_capacity(length as usize);
52 for index in 0..length {
53 let key = local_storage
54 .key(index)
55 .map_err(js_to_error)?
56 .unwrap_throw();
57 let value: Value = Self::get(&key)?;
58 map.insert(key, value);
59 }
60 Ok(serde_json::from_value(Value::Object(map))?)
61 }
62
63 fn set<T>(key: impl AsRef<str>, value: T) -> Result<()>
65 where
66 T: Serialize,
67 {
68 let key = key.as_ref();
69 let value = serde_json::to_string(&value)?;
70 Self::raw()
71 .set_item(key, &value)
72 .map_err(errors::js_to_error)?;
73 Ok(())
74 }
75
76 fn delete(key: impl AsRef<str>) {
78 let key = key.as_ref();
79 Self::raw()
80 .remove_item(key)
81 .expect_throw("unreachable: remove_item does not throw an exception");
82 }
83
84 fn clear() {
86 Self::raw()
87 .clear()
88 .expect_throw("unreachable: clear does not throw an exception");
89 }
90
91 fn length() -> u32 {
93 Self::raw()
94 .length()
95 .expect_throw("unreachable: length does not throw an exception")
96 }
97}