Skip to content

Commit

Permalink
okay well this time it compiles :P
Browse files Browse the repository at this point in the history
  • Loading branch information
expede committed Feb 2, 2024
1 parent f668aa6 commit 5fb875f
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 57 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ getrandom = { version = "0.2", features = ["js"] }
js-sys = { version = "0.3" }
serde-wasm-bindgen = "0.6"
wasm-bindgen = "0.2"
wasm-bindgen-derive = "0.2"
wasm-bindgen-futures = { version = "0.4" }
web-sys = { version = "0.3", features = ["Crypto", "CryptoKey", "CryptoKeyPair", "SubtleCrypto"] }

Expand Down
151 changes: 94 additions & 57 deletions src/ipld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use libipld_core::multihash::MultihashGeneric;
#[cfg(target_arch = "wasm32")]
use js_sys::{Array, Map, Uint8Array};

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_derive::TryFromJsValue;

pub struct Newtype(pub Ipld);

impl From<Ipld> for Newtype {
Expand All @@ -26,23 +29,34 @@ impl From<Newtype> for Ipld {
}
}

// FIXME better name
#[cfg(target_arch = "wasm32")]
#[derive(TryFromJsValue, Debug, PartialEq, Eq, Clone)]
#[wasm_bindgen]
pub struct NewCid {
// FIXME Link?
version_code: u64,
multicodec_code: u64,
multihash_code: u64,
hash_bytes: Vec<u8>,
cid: Cid,
}

#[wasm_bindgen]
extern "C" {
/// This is here because the TryFromJsValue derivation macro
/// doesn't automatically support `Option<T>`.
///
/// [https://docs.rs/wasm-bindgen-derive/0.2.1/wasm_bindgen_derive/#optional-arguments]
#[wasm_bindgen(typescript_type = "NewCid | undefined")]
pub type OptionNewCid;
}

// FIXME better name
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
impl NewCid {
pub fn from_string(cid_string: String) -> Result<Link, JsValue> {
pub fn from_string(cid_string: String) -> Result<NewCid, JsValue> {
NewCid::try_from(cid_string).map_err(|e| JsValue::from_str(&format!("{}", e)))
}

pub fn to_string(&self) -> String {
self.cid.to_string()
}
}

#[cfg(target_arch = "wasm32")]
Expand All @@ -57,31 +71,14 @@ impl TryFrom<String> for NewCid {
#[cfg(target_arch = "wasm32")]
impl From<NewCid> for Cid {
fn from(wrapper: NewCid) -> Self {
Cid::new(
wrapper.version_code.try_into().expect(
"must be a valid Cid::Version because it was deconstructed from a valid one",
),
wrapper
.multicodec_code
.try_into()
.expect("must be a valid Multicodec because it was deconstructed from a valid one"),
MultihashGeneric::<64>::wrap(wrapper.multihash_code, wrapper.hash_bytes.as_ref())
.expect("a valid Multihash because it was deconstructed from a valid one")
.into(),
)
.expect("the only way to get a Link is by deconstructing a valid Cid")
wrapper.cid
}
}

#[cfg(target_arch = "wasm32")]
impl From<Cid> for NewCid {
fn from(cid: Cid) -> Self {
Self {
version_code: cid.version().into(),
multicodec_code: cid.codec().into(),
multihash_code: cid.hash().code(),
hash_bytes: cid.hash().digest().to_vec(),
}
Self { cid }
}
}

Expand All @@ -95,7 +92,13 @@ impl From<Newtype> for JsValue {
Ipld::Integer(i) => JsValue::from(i),
Ipld::Float(f) => JsValue::from_f64(f),
Ipld::String(s) => JsValue::from_str(&s),
Ipld::Bytes(bs) => Bytes::from(bs).into(),
Ipld::Bytes(bs) => {
let mut arr = js_sys::Uint8Array::new(&bs.len().into());
for (i, b) in bs.iter().enumerate() {
arr.set_index(i as u32, *b);
}
arr.into()
}
Ipld::List(ls) => {
let mut arr = Array::new();
for ipld in ls {
Expand Down Expand Up @@ -138,59 +141,93 @@ impl TryFrom<JsValue> for Newtype {
}

if let Some(arr) = js_val.dyn_ref::<Array>() {
let mut ls = Vec::with_capacity(arr.length() as usize);
for a in arr.iter() {
ls.push(Newtype::try_from(a)?.into());
let mut list = vec![];
for x in arr.to_vec().iter() {
let ipld = Newtype::try_from(x.clone())?.into();
list.push(ipld);
}
return Ok(Newtype(Ipld::List(ls)));
}

if let Some(bytes) = js_val.dyn_ref::<Uint8Array>() {
let arr = Uint8Array::new(&bytes.raw.len().into());
return Ok(Newtype(Ipld::List(list)));
}

for (index, item) in bytes.raw.iter().enumerate() {
arr.set_index(index as u32, *item);
if let Some(arr) = js_val.dyn_ref::<Uint8Array>() {
let mut v = vec![];
for item in arr.to_vec().iter() {
v.push(item.clone());
}

return Ok(Newtype(Ipld::Bytes(arr)));
return Ok(Newtype(Ipld::Bytes(v)));
}

if let Some(map) = js_val.dyn_ref::<Map>() {
let mut m = std::collections::BTreeMap::new();
let mut acc = Ok(());

for iter_item in map.entries() {
match iter_item {
Err(_) => return Err(()),
Ok(k) => match k.as_string() {
None => return Err(()),
Some(s) => {
m.insert(s, Newtype::try_from(v)?.0);
},
// Weird order, but correct per the docs
// vvvvvvvvvv
map.for_each(&mut |value, key| {
if acc.is_err() {
return;
}

match key.as_string() {
None => {
acc = Err(());
}
Some(k) => match Newtype::try_from(value.clone()) {
Err(_) => {
acc = Err(());
}
Ok(v) => match Newtype::try_from(value) {
Err(_) => {
acc = Err(());
}
Ok(v) => {
m.insert(k, v.0);
}
},
},
}
}
});

return Ok(Newtype(Ipld::Map(m)));
return acc.map(|_| Newtype(Ipld::Map(m)));
}

// NOTE *must* come before `is_object` (which is hopefully below)
if let Some(link) = js_val.dyn_ref::<NewCid>() {
return Ok(Newtype(Ipld::Link(link.into().clone())));
if let Ok(new_cid) = NewCid::try_from(&js_val) {
return Ok(Newtype(Ipld::Link(new_cid.cid)));
}

if js_val.is_object() {
let mut m = std::collections::BTreeMap::new();
for (k, v) in js_val {
m.insert(k.as_string.ok_or(())?, Newtype::try_from(v)?);
}
let mut acc = Ok(());

// This order is correct per the docs
// vvvvvvvvvv
js_sys::Map::from(js_val).for_each(&mut |value, key| {
if acc.is_err() {
return;
}

match key.as_string() {
None => {
acc = Err(());
}
Some(k) => match Newtype::try_from(value) {
Err(_) => {
acc = Err(());
}
Ok(v) => {
m.insert(k, v.0);
}
},
}
});

return Ok(Newtype(Ipld::Map(m)));
return acc.map(|_| Newtype(Ipld::Map(m)));
}

// // FIXME hmmmm
// if let Some(undefined) = js_val.is_undefined() {
// return Self(Ipld::Null);
// }
// NOTE fails on `undefined` and `function`

Err(())
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

//! ucan

#[cfg(target_arch = "wasm32")]
extern crate alloc;

// use std::str::FromStr;
//
// use cid::{multihash, Cid};
Expand Down

0 comments on commit 5fb875f

Please sign in to comment.