1use inkpad_executor::Memory;
3use inkpad_std::{Rc, Vec};
4use inkpad_support::{
5 traits::{Cache, Frame, Storage},
6 types::State,
7};
8use core::cell::RefCell;
9use wasm_bindgen::prelude::wasm_bindgen;
10
11#[wasm_bindgen]
13pub struct Tree {
14 name: String,
15 storage: web_sys::Storage,
16 frame: Vec<Rc<RefCell<State<Memory>>>>,
17}
18
19#[wasm_bindgen]
20impl Tree {
21 #[wasm_bindgen(constructor)]
22 pub fn new(name: &str) -> Self {
23 let window = web_sys::window().expect("Could not find window");
24 Self {
25 name: name.to_string(),
26 storage: window
27 .local_storage()
28 .expect("Could not find local_storage")
29 .expect("Could not find local_storage"),
30 frame: Vec::new(),
31 }
32 }
33}
34
35fn browser_key(mut name: String, code_hash: Vec<u8>) -> String {
36 name.push_str(&hex::encode(code_hash));
37 name
38}
39
40impl Storage for Tree {
41 fn set(&mut self, key: Vec<u8>, value: Vec<u8>) -> Option<Vec<u8>> {
42 let data_str = serde_json::to_string(&value).ok()?;
43 self.storage
44 .set(&browser_key(self.name.to_string(), key.clone()), &data_str)
45 .map(|_| key)
46 .ok()
47 }
48
49 fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>> {
50 let data_str = serde_json::to_string(&key).ok()?;
51 self.storage
52 .remove_item(&data_str)
53 .ok()
54 .map(|_| key.to_vec())
55 }
56
57 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
58 if let Ok(Some(data)) = self
59 .storage
60 .get(&browser_key(self.name.to_string(), key.to_vec()))
61 {
62 Some(serde_json::from_str(&data).ok()?)
63 } else {
64 None
65 }
66 }
67}
68
69impl Frame<Memory> for Tree {}
70
71impl Cache<Memory> for Tree {
72 fn frame(&self) -> &Vec<Rc<RefCell<State<Memory>>>> {
73 &self.frame
74 }
75
76 fn frame_mut(&mut self) -> &mut Vec<Rc<RefCell<State<Memory>>>> {
77 &mut self.frame
78 }
79
80 fn memory(&self) -> Option<Memory> {
81 Some(self.frame.last()?.borrow().memory.clone())
82 }
83}