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