Skip to content

Instantly share code, notes, and snippets.

@mvolfik
Created March 12, 2022 23:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mvolfik/fc52c71a5fd008a563997c1c25093a81 to your computer and use it in GitHub Desktop.
Save mvolfik/fc52c71a5fd008a563997c1c25093a81 to your computer and use it in GitHub Desktop.
Svelte store contract implemented in Rust using wasm-bindgen. No reason to use to use this on its own, but if you have a larger wasm project, this is handy to use to automatically propagate state changes to the presentation layer
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use js_sys::{Array, Function};
use wasm_bindgen::{
prelude::{wasm_bindgen, Closure},
JsCast, JsValue,
};
#[wasm_bindgen]
pub struct Writable {
value: JsValue,
subscribers: Rc<RefCell<HashMap<u64, Function>>>,
i: u64,
}
#[wasm_bindgen(typescript_custom_section)]
const TS_SECTION_UNSUBSCRIBE_FUNCTION: &'static str =
"export type UnsubscribeFunction = () => void;";
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "UnsubscribeFunction")]
pub type UnsubscribeFunction;
}
#[wasm_bindgen]
impl Writable {
pub fn subscribe(&mut self, subscriber: Function) -> Result<UnsubscribeFunction, JsValue> {
subscriber.call1(&JsValue::UNDEFINED, &self.value)?;
let i = self.i;
self.i += 1;
self.subscribers.borrow_mut().insert(i, subscriber);
let weak_ref = Rc::downgrade(&self.subscribers);
Ok(Closure::once_into_js(Box::new(move || {
if let Some(subs) = weak_ref.upgrade() {
subs.borrow_mut().remove(&i);
}
}))
.unchecked_into())
}
pub fn set(&mut self, val: JsValue) -> Array {
self.value = val;
let errors = Array::new();
for sub in self.subscribers.borrow_mut().values() {
if let Err(e) = sub.call1(&JsValue::UNDEFINED, &self.value) {
errors.push(&e);
}
}
errors
}
#[wasm_bindgen(constructor)]
#[must_use]
pub fn new(value: JsValue) -> Self {
Self {
value,
subscribers: Default::default(),
i: 0,
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment