Skip to content

Commit

Permalink
Learning about Wasm bindgen
Browse files Browse the repository at this point in the history
  • Loading branch information
expede committed Feb 2, 2024
1 parent d8ebca2 commit c8bfde7
Show file tree
Hide file tree
Showing 7 changed files with 371 additions and 178 deletions.
3 changes: 3 additions & 0 deletions src/ability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ pub mod wasm;
pub mod arguments;
pub mod command;

#[cfg(target_arch = "wasm32")]
pub mod js;

// // TODO move to crate::wasm? or hide behind feature flag?
#[cfg(target_arch = "wasm32")]
pub mod dynamic;
Expand Down
18 changes: 8 additions & 10 deletions src/ability/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,20 @@ impl Arguments {
Arguments(iterable.into_iter().collect())
}

pub fn iter(&self) -> impl Iterator<Item = (&String, &Ipld)> {
self.0.iter()
}

pub fn into_iter(self) -> impl Iterator<Item = (String, Ipld)> {
self.0.into_iter()
pub fn get(&self, key: &str) -> Option<&Ipld> {
self.0.get(key)
}
}

impl Arguments {
pub fn insert(&mut self, key: String, value: Ipld) -> Option<Ipld> {
self.0.insert(key, value)
}

pub fn get(&self, key: &str) -> Option<&Ipld> {
self.0.get(key)
pub fn iter(&self) -> impl Iterator<Item = (&String, &Ipld)> {
self.0.iter()
}

pub fn into_iter(self) -> impl Iterator<Item = (String, Ipld)> {
self.0.into_iter()
}
}

Expand Down
303 changes: 141 additions & 162 deletions src/ability/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,180 +21,159 @@ use wasm_bindgen::prelude::*;
// NOTE the lack of checking functions!
// This is meant to be embedded inside of structs that have e.g. FFI bindings to
// a validation function, such as a &js_sys::Function, Ruby magnus::function!, etc etc
#[derive(Clone, PartialEq)]
pub struct Generic<Args, F> {
pub cmd: String,
pub args: Args,
pub is_nonce_meaningful: DefaultTrue,

pub same_validator: F,
pub parent_validator: F, // FIXME needs to be a different types, and fall back to Void
pub shape_validator: F, // FIXME needs to be a different type
}

impl<F> Debug for Generic<Arguments, F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Generic")
.field("cmd", &self.cmd)
.field("args", &self.args)
.field("is_nonce_meaningful", &self.is_nonce_meaningful)
.finish()
}
}

pub type Dynamic<F> = Generic<Arguments, F>;
pub type Promised<F> = Generic<Promise<Arguments>, F>;

impl<Args: Serialize + Clone> Serialize for Generic<Args, ()>
where
Arguments: From<Args>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(2))?;
map.serialize_entry("cmd", &self.cmd)?;
map.serialize_entry("args", &Arguments::from(self.args.clone()))?;
map.end()
}
}

impl<'de, Args: Deserialize<'de>> Deserialize<'de> for Generic<Args, ()> {
fn deserialize<D>(deserializer: D) -> Result<Generic<Args, ()>, D::Error>
where
D: Deserializer<'de>,
{
// FIXME
todo!()
// let btree = BTreeMap::deserialize(deserializer)?;
// Ok(Generic {
// cmd: btree.get("cmd")?.to_string(),
// args: btree.get("args")?.clone(),
// is_nonce_meaningful: DefaultTrue::default(),
//
// same_validator: (),
// parent_validator: (),
// shape_validator: (),
// })
}
}

impl<Args, F> ToCommand for Generic<Args, F> {
fn to_command(&self) -> String {
self.cmd.clone()
}
}

impl<F> Delegatable for Dynamic<F> {
type Builder = Dynamic<F>;
}

impl<F> Resolvable for Dynamic<F> {
type Promised = Promised<F>;
}

impl<Args: Serialize> From<Generic<Args, ()>> for Ipld {
fn from(generic: Generic<Args, ()>) -> Self {
generic.into()
}
}

impl<Args: DeserializeOwned> TryFrom<Ipld> for Generic<Args, ()> {
type Error = SerdeError;

fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
ipld_serde::from_ipld(ipld)
}
}

impl<Args: Into<Arguments>, F> From<Generic<Args, F>> for Arguments {
fn from(generic: Generic<Args, F>) -> Self {
generic.args.into()
}
}

impl<F> TryFrom<Promised<F>> for Dynamic<F> {
type Error = (); // FIXME

fn try_from(awaiting: Promised<F>) -> Result<Self, ()> {
if let Promise::Resolved(args) = &awaiting.args {
Ok(Dynamic {
cmd: awaiting.cmd,
args: args.clone(),

same_validator: awaiting.same_validator,
parent_validator: awaiting.parent_validator,
shape_validator: awaiting.shape_validator,
is_nonce_meaningful: awaiting.is_nonce_meaningful,
})
} else {
Err(())
}
}
}

impl<F> From<Dynamic<F>> for Promised<F> {
fn from(d: Dynamic<F>) -> Self {
Promised {
cmd: d.cmd,
args: Promise::Resolved(d.args),

same_validator: d.same_validator,
parent_validator: d.parent_validator,
shape_validator: d.shape_validator,
is_nonce_meaningful: d.is_nonce_meaningful,
}
}
}

impl<F> Checkable for Dynamic<F>
where
F: Fn(&String, &Arguments) -> Result<(), String>,
{
type Hierarchy = Parentless<Dynamic<F>>; // FIXME I bet we can revover parents
}
// #[derive(Clone, PartialEq)]
// pub struct Generic<Args, F> {
// pub cmd: String,
// pub args: Args,
// // pub is_nonce_meaningful: Fn(&String) -> bool,
// // pub same_validator: Fn(&String, &Arguments) -> Result<(), String>,
// // pub parent_validator: F, // FIXME needs to be a different types, and fall back to Void
// // pub shape_validator: Fn(&String, &Arguments) -> Result<(), String>, // FIXME needs to be a different type
// }

// FIXME Actually, we shoudl go back to wrapping?
// impl<F> CheckSame for Dynamic<F>
// // pub struct DynamicValidator {
// // fn check_shape(self) -> ();
// // // fn check_same: Fn(&String, &Arguments, &String, &Arguments) -> Result<(), String>,
// // // fn check_parents: Fn(&String, &Arguments, &String, &Arguments) -> Result<(), String>,
// // }
// //
// //
// //
// // // FIXME Actually, we shoudl go back to wrapping?
// // // impl<F> CheckSame for Dynamic<F>
// // // where
// // // F: Fn(&String, &Arguments) -> Result<(), String>,
// // // {
// // // type Error = String;
// // //
// // // fn check_same(&self, proof: &Self) -> Result<(), Self::Error> {
// // // let chain_checker = &self.same_validator;
// // // let shape_checker = &self.same_validator;
// // //
// // // shape_checker(&proof.cmd, &proof.args)?;
// // // chain_checker(&proof.cmd, &proof.args)
// // // }
// // // }
//
// impl<F> Debug for Generic<Arguments, F> {
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// f.debug_struct("Generic")
// .field("cmd", &self.cmd)
// .field("args", &self.args)
// .field("is_nonce_meaningful", &self.is_nonce_meaningful)
// .finish()
// }
// }
//
// pub type Dynamic<F> = Generic<Arguments, F>;
// pub type Promised<F> = Generic<Promise<Arguments>, F>;
//
// impl<Args: Serialize + Clone> Serialize for Generic<Args, ()>
// where
// F: Fn(&String, &Arguments) -> Result<(), String>,
// Arguments: From<Args>,
// {
// type Error = String;
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
// where
// S: Serializer,
// {
// let mut map = serializer.serialize_map(Some(2))?;
// map.serialize_entry("cmd", &self.cmd)?;
// map.serialize_entry("args", &Arguments::from(self.args.clone()))?;
// map.end()
// }
// }
//
// fn check_same(&self, proof: &Self) -> Result<(), Self::Error> {
// let chain_checker = &self.same_validator;
// let shape_checker = &self.same_validator;
// impl<'de, Args: Deserialize<'de>> Deserialize<'de> for Generic<Args, ()> {
// fn deserialize<D>(deserializer: D) -> Result<Generic<Args, ()>, D::Error>
// where
// D: Deserializer<'de>,
// {
// // FIXME
// todo!()
// // let btree = BTreeMap::deserialize(deserializer)?;
// // Ok(Generic {
// // cmd: btree.get("cmd")?.to_string(),
// // args: btree.get("args")?.clone(),
// // is_nonce_meaningful: DefaultTrue::default(),
// //
// // same_validator: (),
// // parent_validator: (),
// // shape_validator: (),
// // })
// }
// }
//
// shape_checker(&proof.cmd, &proof.args)?;
// chain_checker(&proof.cmd, &proof.args)
// impl<Args, F> ToCommand for Generic<Args, F> {
// fn to_command(&self) -> String {
// self.cmd.clone()
// }
// }

// #[wasm_bindgen(module = "./ability")]
// extern "C" {
// type JsAbility;
//
// // FIXME wrap in func that checks the jsval or better: converts form Ipld
// #[wasm_bindgen(constructor)]
// fn new(cmd: String, args: BTreeMap<String, JsValue>) -> JsAbility;
// impl<F> Delegatable for Dynamic<F> {
// type Builder = Dynamic<F>;
// }
//
// #[wasm_bindgen(method, getter)]
// fn command(this: &JsAbility) -> String;
// impl<F> Resolvable for Dynamic<F> {
// type Promised = Promised<F>;
// }
//
// #[wasm_bindgen(method, getter)]
// fn arguments(this: &JsAbility) -> Arguments;
// impl<Args: Serialize> From<Generic<Args, ()>> for Ipld {
// fn from(generic: Generic<Args, ()>) -> Self {
// generic.into()
// }
// }
//
// #[wasm_bindgen(method, getter)]
// fn is_nonce_meaningful(this: &JsAbility) -> bool;
// impl<Args: DeserializeOwned> TryFrom<Ipld> for Generic<Args, ()> {
// type Error = SerdeError;
//
// // e.g. reject extra fields
// #[wasm_bindgen(method)]
// fn validate_shape(this: &JsAbility) -> bool;
// fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
// ipld_serde::from_ipld(ipld)
// }
// }
//
// // FIXME camels to snakes
// #[wasm_bindgen(method)]
// fn check_same(this: &JsAbility, proof: &JsAbility) -> Result<(), String>;
// impl<Args: Into<Arguments>, F> From<Generic<Args, F>> for Arguments {
// fn from(generic: Generic<Args, F>) -> Self {
// generic.args.into()
// }
// }
//
// fn check_parents(th.......)
// impl<F> TryFrom<Promised<F>> for Dynamic<F> {
// type Error = (); // FIXME
//
// fn try_from(awaiting: Promised<F>) -> Result<Self, ()> {
// if let Promise::Resolved(args) = &awaiting.args {
// Ok(Dynamic {
// cmd: awaiting.cmd,
// args: args.clone(),
//
// same_validator: awaiting.same_validator,
// parent_validator: awaiting.parent_validator,
// shape_validator: awaiting.shape_validator,
// is_nonce_meaningful: awaiting.is_nonce_meaningful,
// })
// } else {
// Err(())
// }
// }
// }
//
// impl<F> From<Dynamic<F>> for Promised<F> {
// fn from(d: Dynamic<F>) -> Self {
// Promised {
// cmd: d.cmd,
// args: Promise::Resolved(d.args),
//
// same_validator: d.same_validator,
// parent_validator: d.parent_validator,
// shape_validator: d.shape_validator,
// is_nonce_meaningful: d.is_nonce_meaningful,
// }
// }
// }
//
// impl<F> Checkable for Dynamic<F>
// where
// F: Fn(&String, &Arguments) -> Result<(), String>,
// {
// type Hierarchy = Parentless<Dynamic<F>>; // FIXME I bet we can revover parents
// }
Loading

0 comments on commit c8bfde7

Please sign in to comment.