quad_storage/
lib.rs

1#![allow(unused_variables)]
2
3//! # quad-storage
4//!
5//! This is the crate to save data in persistent local storage in miniquad/macroquad environment. In WASM the data persists even if tab or browser are closed. To achieve that [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) is used. To save data on native platforms, data is just saved to the local file named `local.data`.
6//!
7//! [Web demo.](https://optozorax.github.io/quad-storage/)
8//!
9//! # Code example
10//! ```rust
11//! let storage = &mut quad_storage::STORAGE.lock().unwrap();
12//! storage.set("test", "value");
13//! let value = storage.get("test").unwrap();
14//! assert_eq!(value, "value");
15//! ```
16//!
17//! # Usage
18//! Add this to your `Cargo.toml` dependencies:
19//! ```text
20//! quad-storage = "0.1.0"
21//! ```
22//! # Usage in WASM
23//! Add file [`quad-storage/js/quad-storage.js`](https://github.com/optozorax/quad-storage/blob/master/js/quad-storage.js) to your project.
24//!
25//! Add file [`sapp-jsutils/js/sapp_jsutils.js`](https://github.com/not-fl3/sapp-jsutils/blob/master/js/sapp_jsutils.js) file to your project.
26//!
27//! Add this lines after loading of `gl.js` and before loading of your wasm in your `index.html`:
28//! ```html
29//! <script src="sapp_jsutils.js"></script>
30//! <script src="quad-storage.js"></script>
31//! ```
32//! Done! Now you can use this crate.
33
34use lazy_static::lazy_static;
35use std::sync::Mutex;
36
37#[cfg(target_arch = "wasm32")]
38use quad_storage_sys::*;
39
40#[cfg(not(target_arch = "wasm32"))]
41use nanoserde::{DeJson, SerJson};
42
43#[cfg(not(target_arch = "wasm32"))]
44use std::collections::HashMap;
45
46/// The local storage with methods to read and write data.
47#[cfg_attr(not(target_arch = "wasm32"), derive(DeJson, SerJson))]
48pub struct LocalStorage {
49    #[cfg(not(target_arch = "wasm32"))]
50    local: HashMap<String, String>,
51}
52
53#[cfg(not(target_arch = "wasm32"))]
54const LOCAL_FILE: &str = "local.data";
55
56impl Default for LocalStorage {
57    fn default() -> Self {
58        #[cfg(target_arch = "wasm32")]
59        {
60            Self {}
61        }
62        #[cfg(not(target_arch = "wasm32"))]
63        {
64            if let Ok(file) = std::fs::read_to_string(LOCAL_FILE) {
65                LocalStorage::deserialize_json(&file).unwrap()
66            } else {
67                LocalStorage {
68                    local: Default::default(),
69                }
70            }
71        }
72    }
73}
74
75impl LocalStorage {
76    #[allow(clippy::len_without_is_empty)]
77    pub fn len(&self) -> usize {
78        #[cfg(target_arch = "wasm32")]
79        {
80            len()
81        }
82        #[cfg(not(target_arch = "wasm32"))]
83        {
84            self.local.len()
85        }
86    }
87
88    /// Get key by its position
89    pub fn key(&self, pos: usize) -> Option<String> {
90        #[cfg(target_arch = "wasm32")]
91        {
92            key(pos)
93        }
94        #[cfg(not(target_arch = "wasm32"))]
95        {
96            self.local.keys().nth(pos).cloned()
97        }
98    }
99
100    pub fn get(&self, key: &str) -> Option<String> {
101        #[cfg(target_arch = "wasm32")]
102        {
103            get(key)
104        }
105        #[cfg(not(target_arch = "wasm32"))]
106        {
107            self.local.get(key).cloned()
108        }
109    }
110    pub fn set(&mut self, key: &str, value: &str) {
111        #[cfg(target_arch = "wasm32")]
112        {
113            set(key, value)
114        }
115        #[cfg(not(target_arch = "wasm32"))]
116        {
117            self.local.insert(key.to_string(), value.to_string());
118            self.save();
119        }
120    }
121    pub fn remove(&mut self, key: &str) {
122        #[cfg(target_arch = "wasm32")]
123        {
124            remove(key)
125        }
126        #[cfg(not(target_arch = "wasm32"))]
127        {
128            self.local.remove(key);
129            self.save();
130        }
131    }
132    pub fn clear(&mut self) {
133        #[cfg(target_arch = "wasm32")]
134        {
135            clear()
136        }
137        #[cfg(not(target_arch = "wasm32"))]
138        {
139            self.local.clear();
140            self.save();
141        }
142    }
143
144    #[cfg(not(target_arch = "wasm32"))]
145    fn save(&self) {
146        std::fs::write(LOCAL_FILE, self.serialize_json()).unwrap();
147    }
148}
149
150lazy_static! {
151    /// Global singleton to access [`LocalStorage`].
152    ///
153    /// Usage:
154    /// ```rust
155    /// let storage = &mut quad_storage::STORAGE.lock().unwrap();
156    /// ```
157    pub static ref STORAGE: Mutex<LocalStorage> = Mutex::new(Default::default());
158}