oxygengine_backend_web/
storage.rs

1use core::storage::{StorageEngine, StorageError, StorageResult};
2use std::fmt::Write;
3
4fn window() -> web_sys::Window {
5    web_sys::window().expect("no global `window` exists")
6}
7
8#[derive(Default, Copy, Clone)]
9pub struct WebStorageEngine;
10
11impl StorageEngine for WebStorageEngine {
12    fn load(&mut self, path: &str) -> StorageResult<Vec<u8>> {
13        if let Ok(Some(storage)) = window().local_storage() {
14            if let Ok(Some(data)) = storage.get_item(path) {
15                Self::str_to_bytes(&data)
16            } else {
17                Err(StorageError::CouldNotLoadData(format!(
18                    "Could not load data from: {}",
19                    path
20                )))
21            }
22        } else {
23            Err(StorageError::CouldNotLoadData(format!(
24                "Could not load data from: {}",
25                path
26            )))
27        }
28    }
29
30    fn store(&mut self, path: &str, data: &[u8]) -> StorageResult<()> {
31        if let Ok(Some(storage)) = window().local_storage() {
32            if storage
33                .set_item(path, &Self::bytes_to_string(data)?)
34                .is_ok()
35            {
36                Ok(())
37            } else {
38                Err(StorageError::CouldNotStoreData(format!(
39                    "Could not store data to: {}",
40                    path
41                )))
42            }
43        } else {
44            Err(StorageError::CouldNotStoreData(format!(
45                "Could not store data to: {}",
46                path
47            )))
48        }
49    }
50}
51
52impl WebStorageEngine {
53    fn str_to_bytes(data: &str) -> StorageResult<Vec<u8>> {
54        let mut result = Vec::with_capacity(data.len() / 2);
55        for i in 0..data.len() / 2 {
56            let chunk = &data[(i * 2)..(i * 2 + 2)];
57            if let Ok(byte) = u8::from_str_radix(chunk, 16) {
58                result.push(byte);
59            } else {
60                return Err(StorageError::CouldNotStoreData(format!(
61                    "Could not convert to byte: {}",
62                    chunk
63                )));
64            }
65        }
66        Ok(result)
67    }
68
69    fn bytes_to_string(data: &[u8]) -> StorageResult<String> {
70        let mut result = String::with_capacity(data.len() * 2);
71        for byte in data {
72            if write!(&mut result, "{:02X}", byte).is_err() {
73                return Err(StorageError::CouldNotStoreData(format!(
74                    "Could not convert byte: {}",
75                    byte
76                )));
77            }
78        }
79        Ok(result)
80    }
81}