#![deny(missing_docs, missing_debug_implementations)]
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use crate::errors::js_to_error;
use errors::StorageError;
use serde_json::{Map, Value};
pub mod errors;
mod local_storage;
mod session_storage;
pub use local_storage::LocalStorage;
pub use session_storage::SessionStorage;
pub type Result<T> = std::result::Result<T, StorageError>;
pub trait Storage {
fn raw() -> web_sys::Storage;
fn get<T>(key: impl AsRef<str>) -> Result<T>
where
T: for<'de> Deserialize<'de>,
{
let key = key.as_ref();
let item = Self::raw()
.get_item(key)
.expect_throw("unreachable: get_item does not throw an exception")
.ok_or_else(|| StorageError::KeyNotFound(key.to_string()))?;
let item = serde_json::from_str(&item)?;
Ok(item)
}
fn get_all<T>() -> Result<T>
where
T: for<'a> Deserialize<'a>,
{
let local_storage = Self::raw();
let length = Self::length();
let mut map = Map::with_capacity(length as usize);
for index in 0..length {
let key = local_storage
.key(index)
.map_err(js_to_error)?
.unwrap_throw();
let value: Value = Self::get(&key)?;
map.insert(key, value);
}
Ok(serde_json::from_value(Value::Object(map))?)
}
fn set<T>(key: impl AsRef<str>, value: T) -> Result<()>
where
T: Serialize,
{
let key = key.as_ref();
let value = serde_json::to_string(&value)?;
Self::raw()
.set_item(key, &value)
.map_err(errors::js_to_error)?;
Ok(())
}
fn delete(key: impl AsRef<str>) {
let key = key.as_ref();
Self::raw()
.remove_item(key)
.expect_throw("unreachable: remove_item does not throw an exception");
}
fn clear() {
Self::raw()
.clear()
.expect_throw("unreachable: clear does not throw an exception");
}
fn length() -> u32 {
Self::raw()
.length()
.expect_throw("unreachable: length does not throw an exception")
}
}