Skip to content

Add wrapper for localStorage and sessionStorage #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ranile opened this issue May 2, 2021 · 1 comment · Fixed by #125
Closed

Add wrapper for localStorage and sessionStorage #124

ranile opened this issue May 2, 2021 · 1 comment · Fixed by #125

Comments

@ranile
Copy link
Collaborator

ranile commented May 2, 2021

Summary

Add wrappers for browser's storage interface. These will wrap around localStorage and sessionStorage and provide an idiomatic Rust API.

Motivation

It's hard to deal with web-sys directly and using storage in browser is a common case.

Detailed Explanation

We provide a trait with default implementations for dealing with web_sys::Storage. The web_sys::Storage instance to be used is provided by the raw method which must be implemented by the implementers of the trait. We use serde to serialize and deserialize data to and from JSON which is stored in the browser-provided storage.

pub struct JsError {
    pub name: String,
    pub message: String,
    /// Holds the value returned by calling `toString` on the error. This is used by `Display` impl.
    js_to_string: String,
}

#[derive(Debug, thiserror::Error)]
pub enum StorageError {
    #[error("{0}")]
    SerdeError(#[from] serde_json::Error),
    #[error("key {0} not found")]
    KeyNotFound(String),
    #[error("{0}")]
    JsError(JsError),
}

pub type Result<T> = std::result::Result<T, StorageError>;

pub trait Storage {
    /// Get the raw [`web_sys::Storage`] instance
    fn raw() -> web_sys::Storage;

    /// Get the value for the specified key
    fn get<T>(key: impl AsRef<str>) -> Result<T>
    where
        T: for<'de> Deserialize<'de>,
    { ... }

    /// Get all the stored keys and their values
    fn get_all<T>() -> Result<T>
    where
        T: for<'a> Deserialize<'a>,
    { ... }

    /// Insert a value for the specified key
    fn set<T>(key: impl AsRef<str>, value: T) -> Result<()>
    where
        T: Serialize,
    { ... }

    /// Remove a key and it's stored value
    fn delete(key: impl AsRef<str>) { ... }

    /// Remove all the stored data
    fn clear() { ... }

    /// Get the number of items stored
    fn length() -> u32 { ... }
}

pub struct LocalStorage;

impl Storage for LocalStorage {
    fn raw() -> web_sys::Storage { ... }
}

pub struct SessionStorage;

impl Storage for SessionStorage {
    fn raw() -> web_sys::Storage { ... }
}

Drawbacks, Rationale, and Alternatives

Alternative Approach

Provide an API with a single struct that's holds on to a web_sys::Storage instance and performs operations with that.

pub enum Area {
    Local,
    Session,
}
pub struct Storage {
    storage: web_sys::Storage,
}

impl Storage {
    pub fn new(area: Area) -> Self { ... }
}

Unresolved Questions

None

@ranile
Copy link
Collaborator Author

ranile commented May 4, 2021

I just learnt that Web Storage API only covers localStorage and sessionStorage so this crate should cover only those too. I've removed mentions of other storage from the issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant