Skip to content

Commit

Permalink
Added guest-side seq, map, enum access
Browse files Browse the repository at this point in the history
  • Loading branch information
juntyr committed Sep 30, 2022
1 parent c7bd663 commit 960081b
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 15 deletions.
12 changes: 7 additions & 5 deletions necsim/plugins/wasm/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,11 +1247,13 @@ impl<'de, 'a> serde::de::EnumAccess<'de> for &'a mut dyn EnumAccess<'de> {
}

pub struct Variant<'de> {
data: Any,
unit_variant: unsafe fn(Any) -> Result<(), Error>,
visit_newtype: unsafe fn(Any, seed: &mut dyn DeserializeSeed<'de>) -> Result<Out, Error>,
tuple_variant: unsafe fn(Any, len: usize, visitor: &mut dyn Visitor<'de>) -> Result<Out, Error>,
struct_variant: unsafe fn(
pub(crate) data: Any,
pub(crate) unit_variant: unsafe fn(Any) -> Result<(), Error>,
pub(crate) visit_newtype:
unsafe fn(Any, seed: &mut dyn DeserializeSeed<'de>) -> Result<Out, Error>,
pub(crate) tuple_variant:
unsafe fn(Any, len: usize, visitor: &mut dyn Visitor<'de>) -> Result<Out, Error>,
pub(crate) struct_variant: unsafe fn(
Any,
fields: &'static [&'static str],
visitor: &mut dyn Visitor<'de>,
Expand Down
259 changes: 252 additions & 7 deletions necsim/plugins/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ mod map;
wit_bindgen_rust::import!("src/serde-wasm-host.wit");
wit_bindgen_rust::export!("src/serde-wasm-guest.wit");

struct DeValue {
#[doc(hidden)]
pub struct DeValue {
inner: RefCell<Option<de::Out>>,
}

struct DeserializeSeed {
inner: Box<RefCell<dyn de::DeserializeSeed<'static>>>,
#[doc(hidden)]
pub struct DeserializeSeed {
inner: RefCell<&'static mut dyn de::DeserializeSeed<'static>>,
}

impl serde_wasm_guest::DeserializeSeed for DeserializeSeed {
Expand All @@ -32,7 +34,8 @@ impl serde_wasm_guest::DeserializeSeed for DeserializeSeed {
}
}

struct Visitor {
#[doc(hidden)]
pub struct Visitor {
inner: RefCell<&'static mut dyn de::Visitor<'static>>,
}

Expand Down Expand Up @@ -61,6 +64,70 @@ fn map_bridge_result(
}
}

fn map_bridge_option_result(
result: Result<Option<serde_wasm_host::DeValueHandle>, serde_wasm_host::DeError>,
) -> Result<Option<de::Out>, Error> {
match result {
Ok(Some(handle)) => {
let handle: wit_bindgen_rust::Handle<DeValue> =
unsafe { wit_bindgen_rust::Handle::from_raw(handle.handle) };
let out = handle.inner.borrow_mut().take().unwrap();
Ok(Some(out))
},
Ok(None) => Ok(None),
Err(err) => Err(Error { inner: err }),
}
}

fn map_bridge_option_pair_result(
result: Result<
Option<(
serde_wasm_host::DeValueHandle,
serde_wasm_host::DeValueHandle,
)>,
serde_wasm_host::DeError,
>,
) -> Result<Option<(de::Out, de::Out)>, Error> {
match result {
Ok(Some((handle_a, handle_b))) => {
let handle_a: wit_bindgen_rust::Handle<DeValue> =
unsafe { wit_bindgen_rust::Handle::from_raw(handle_a.handle) };
let out_a = handle_a.inner.borrow_mut().take().unwrap();

let handle_b: wit_bindgen_rust::Handle<DeValue> =
unsafe { wit_bindgen_rust::Handle::from_raw(handle_b.handle) };
let out_b = handle_b.inner.borrow_mut().take().unwrap();

Ok(Some((out_a, out_b)))
},
Ok(None) => Ok(None),
Err(err) => Err(Error { inner: err }),
}
}

fn map_bridge_enum_result(
result: Result<
(
serde_wasm_host::DeValueHandle,
serde_wasm_host::VariantAccess,
),
serde_wasm_host::DeError,
>,
) -> Result<(de::Out, VariantAccess), Error> {
match result {
Ok((handle, variant)) => {
let handle: wit_bindgen_rust::Handle<DeValue> =
unsafe { wit_bindgen_rust::Handle::from_raw(handle.handle) };
let out = handle.inner.borrow_mut().take().unwrap();

let variant = VariantAccess { inner: variant };

Ok((out, variant))
},
Err(err) => Err(Error { inner: err }),
}
}

impl From<Error> for serde_wasm_guest::DeErrorHandle {
fn from(err: Error) -> Self {
Self {
Expand All @@ -77,6 +144,30 @@ impl From<serde_wasm_guest::DeserializerHandle> for Deserializer {
}
}

impl From<serde_wasm_guest::SeqAccessHandle> for SeqAccess {
fn from(seq: serde_wasm_guest::SeqAccessHandle) -> Self {
Self {
inner: unsafe { serde_wasm_host::SeqAccess::from_raw(seq.handle) },
}
}
}

impl From<serde_wasm_guest::MapAccessHandle> for MapAccess {
fn from(map: serde_wasm_guest::MapAccessHandle) -> Self {
Self {
inner: unsafe { serde_wasm_host::MapAccess::from_raw(map.handle) },
}
}
}

impl From<serde_wasm_guest::EnumAccessHandle> for EnumAccess {
fn from(r#enum: serde_wasm_guest::EnumAccessHandle) -> Self {
Self {
inner: unsafe { serde_wasm_host::EnumAccess::from_raw(r#enum.handle) },
}
}
}

impl<'a, 'de> From<&'a mut dyn de::Visitor<'de>> for serde_wasm_host::VisitorHandle {
fn from(visitor: &'a mut dyn de::Visitor<'de>) -> Self {
let visitor: &'static mut dyn de::Visitor<'static> =
Expand All @@ -93,6 +184,24 @@ impl<'a, 'de> From<&'a mut dyn de::Visitor<'de>> for serde_wasm_host::VisitorHan
}
}

impl<'a, 'de> From<&'a mut dyn de::DeserializeSeed<'de>>
for serde_wasm_host::DeserializeSeedHandle
{
fn from(deserialize_seed: &'a mut dyn de::DeserializeSeed<'de>) -> Self {
let deserialize_seed: &'static mut dyn de::DeserializeSeed<'static> =
unsafe { std::mem::transmute(deserialize_seed) };
let deserialize_seed = DeserializeSeed {
inner: RefCell::new(deserialize_seed),
};

let handle = wit_bindgen_rust::Handle::new(deserialize_seed);

Self {
handle: wit_bindgen_rust::Handle::into_raw(handle),
}
}
}

impl serde_wasm_guest::Visitor for Visitor {
fn erased_expecting(&self) -> Option<String> {
struct Expecting<'a>(&'a Visitor);
Expand Down Expand Up @@ -281,21 +390,33 @@ impl serde_wasm_guest::Visitor for Visitor {
&self,
seq: serde_wasm_guest::SeqAccessHandle,
) -> Result<wit_bindgen_rust::Handle<DeValue>, serde_wasm_guest::DeErrorHandle> {
todo!()
map_erased_result(
self.inner
.borrow_mut()
.erased_visit_seq(&mut SeqAccess::from(seq)),
)
}

fn erased_visit_map(
&self,
map: serde_wasm_guest::MapAccessHandle,
) -> Result<wit_bindgen_rust::Handle<DeValue>, serde_wasm_guest::DeErrorHandle> {
todo!()
map_erased_result(
self.inner
.borrow_mut()
.erased_visit_map(&mut MapAccess::from(map)),
)
}

fn erased_visit_enum(
&self,
data: serde_wasm_guest::EnumAccessHandle,
) -> Result<wit_bindgen_rust::Handle<DeValue>, serde_wasm_guest::DeErrorHandle> {
todo!()
map_erased_result(
self.inner
.borrow_mut()
.erased_visit_enum(&mut EnumAccess::from(data)),
)
}
}

Expand All @@ -321,6 +442,12 @@ impl From<usize> for serde_wasm_host::Usize {
}
}

impl From<serde_wasm_host::Usize> for usize {
fn from(size: serde_wasm_host::Usize) -> Self {
size.size as usize
}
}

pub struct Error {
inner: serde_wasm_host::DeError,
}
Expand Down Expand Up @@ -424,6 +551,124 @@ impl<'a> From<serde::de::Unexpected<'a>> for serde_wasm_host::Unexpected<'a> {
}
}

struct SeqAccess {
inner: serde_wasm_host::SeqAccess,
}

impl<'de> de::SeqAccess<'de> for SeqAccess {
fn erased_next_element(
&mut self,
d: &mut dyn de::DeserializeSeed<'de>,
) -> Result<Option<de::Out>, Error> {
map_bridge_option_result(self.inner.erased_next_element(d.into()))
}

fn erased_size_hint(&self) -> Option<usize> {
self.inner.erased_size_hint().map(Into::into)
}
}

struct MapAccess {
inner: serde_wasm_host::MapAccess,
}

impl<'de> de::MapAccess<'de> for MapAccess {
fn erased_next_key(
&mut self,
d: &mut dyn de::DeserializeSeed<'de>,
) -> Result<Option<de::Out>, Error> {
map_bridge_option_result(self.inner.erased_next_key(d.into()))
}

fn erased_next_value(
&mut self,
d: &mut dyn de::DeserializeSeed<'de>,
) -> Result<de::Out, Error> {
map_bridge_result(self.inner.erased_next_value(d.into()))
}

fn erased_next_entry(
&mut self,
key: &mut dyn de::DeserializeSeed<'de>,
value: &mut dyn de::DeserializeSeed<'de>,
) -> Result<Option<(de::Out, de::Out)>, Error> {
map_bridge_option_pair_result(self.inner.erased_next_entry(key.into(), value.into()))
}

fn erased_size_hint(&self) -> Option<usize> {
self.inner.erased_size_hint().map(Into::into)
}
}

struct EnumAccess {
inner: serde_wasm_host::EnumAccess,
}

impl<'de> de::EnumAccess<'de> for EnumAccess {
fn erased_variant_seed(
&mut self,
d: &mut dyn de::DeserializeSeed<'de>,
) -> Result<(de::Out, de::Variant<'de>), Error> {
let (value, variant) = map_bridge_enum_result(self.inner.erased_variant_seed(d.into()))?;

let erased_variant = de::Variant {
data: unsafe { any::Any::new(variant) },
unit_variant: {
unsafe fn unit_variant(a: any::Any) -> Result<(), Error> {
let variant = a.take::<VariantAccess>();

variant
.inner
.unit_variant()
.map_err(|err| Error { inner: err })
}
unit_variant
},
visit_newtype: {
unsafe fn visit_newtype(
a: any::Any,
seed: &mut dyn de::DeserializeSeed,
) -> Result<de::Out, Error> {
let variant = a.take::<VariantAccess>();

map_bridge_result(variant.inner.newtype_variant_seed(seed.into()))
}
visit_newtype
},
tuple_variant: {
unsafe fn tuple_variant(
a: any::Any,
len: usize,
visitor: &mut dyn de::Visitor,
) -> Result<de::Out, Error> {
let variant = a.take::<VariantAccess>();

map_bridge_result(variant.inner.tuple_variant(len.into(), visitor.into()))
}
tuple_variant
},
struct_variant: {
unsafe fn struct_variant(
a: any::Any,
fields: &'static [&'static str],
visitor: &mut dyn de::Visitor,
) -> Result<de::Out, Error> {
let variant = a.take::<VariantAccess>();

map_bridge_result(variant.inner.struct_variant(fields, visitor.into()))
}
struct_variant
},
};

Ok((value, erased_variant))
}
}

struct VariantAccess {
inner: serde_wasm_host::VariantAccess,
}

struct Deserializer {
inner: serde_wasm_host::Deserializer,
}
Expand Down
5 changes: 2 additions & 3 deletions necsim/plugins/wasm/src/serde-wasm-host.wit
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ resource deserializer {
}

resource seq-access {
erased-next-element: func(seed: deserialize-seed-handle) -> expected<de-value-handle, de-error>
erased-next-element: func(seed: deserialize-seed-handle) -> expected<option<de-value-handle>, de-error>
erased-size-hint: func() -> option<usize>
}

Expand All @@ -82,13 +82,12 @@ resource map-access {
}

resource enum-access {
erased-variant: func(seed: deserialize-seed-handle) -> expected<tuple<de-value-handle, variant-access>, de-error>
erased-variant-seed: func(seed: deserialize-seed-handle) -> expected<tuple<de-value-handle, variant-access>, de-error>
}

resource variant-access {
unit-variant: func() -> expected<unit, de-error>
newtype-variant-seed: func(seed: deserialize-seed-handle) -> expected<de-value-handle, de-error>
newtype-variant: func() -> expected<de-value-handle, de-error>
tuple-variant: func(len: usize, visitor: visitor-handle) -> expected<de-value-handle, de-error>
struct-variant: func(fields: list<string>, visitor: visitor-handle) -> expected<de-value-handle, de-error>
}
Expand Down

0 comments on commit 960081b

Please sign in to comment.