use crate::{Error, FromErlNif, List, ListIterator, Map, MapIterator, Result, Term}; use serde::{de::IntoDeserializer, Deserializer}; impl<'de> serde::de::Deserializer<'de> for Term<'de> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { if self.is_atom() || self.is_binary() || self.is_bitstring() { self.deserialize_str(visitor) } else if self.is_float() { self.deserialize_f64(visitor) } else if self.is_fun() { Err(Error::message("cannot deserialize from fun")) } else if self.is_integer() { self.deserialize_i64(visitor) } else if self.is_list() { self.deserialize_seq(visitor) } else if self.is_map() { self.deserialize_map(visitor) } else if self.is_pid() { Err(Error::message("cannot deserialize from pid")) } else if self.is_port() { Err(Error::message("cannot deserialize from port")) } else if self.is_reference() { Err(Error::message("cannot deserialize from reference")) } else if self.is_tuple() { self.deserialize_seq(visitor) } else { Err(Error::message("unknown term type")) } } fn deserialize_bool(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_bool(bool::from_erl_nif(self)?) } fn deserialize_i8(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_i8(i8::from_erl_nif(self)?) } fn deserialize_i16(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_i16(i16::from_erl_nif(self)?) } fn deserialize_i32(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_i32(i32::from_erl_nif(self)?) } fn deserialize_i64(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_i64(i64::from_erl_nif(self)?) } fn deserialize_u8(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_u8(u8::from_erl_nif(self)?) } fn deserialize_u16(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_u16(u16::from_erl_nif(self)?) } fn deserialize_u32(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_u32(u32::from_erl_nif(self)?) } fn deserialize_u64(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_u64(u64::from_erl_nif(self)?) } fn deserialize_f32(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_f32(f32::from_erl_nif(self)?) } fn deserialize_f64(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_f64(f64::from_erl_nif(self)?) } fn deserialize_char(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_str(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_string(String::from_erl_nif(self)?) } fn deserialize_string(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_string(String::from_erl_nif(self)?) } fn deserialize_bytes(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_option(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { if self .as_atom() .and_then(|atom| atom.get()) .map(|atom| atom == "nil") .unwrap_or(false) { visitor.visit_none() } else { visitor.visit_some(self) } } fn deserialize_unit(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { if self .as_atom() .and_then(|atom| atom.get()) .map(|atom| atom == "nil") .unwrap_or(false) { visitor.visit_unit() } else { Err(Error::message("expected :nil")) } } fn deserialize_unit_struct( self, _name: &'static str, visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_unit(visitor) } fn deserialize_newtype_struct( self, _name: &'static str, visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_seq(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_seq(SeqDeserializer::new(self.as_list()?)?) } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_tuple_struct( self, _name: &'static str, _len: usize, visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_map(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { visitor.visit_map(MapDeserializer::new(self.as_map()?)?) } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_enum( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { if self.is_tuple() { let tuple = self.as_tuple()?; let terms = tuple.get()?; let mut iter = terms.into_iter(); let atom = iter .next() .ok_or_else(|| Error::message("enum must be a tuple with two values"))?; let atom = atom.as_atom()?; let variant = atom.get()?; let value = iter .next() .ok_or_else(|| Error::message("enum must be a tuple with two values"))?; visitor.visit_enum(EnumDeserializer { variant, value: Some(value), }) } else if self.is_atom() { let variant = self.as_atom()?.get()?; visitor.visit_enum(EnumDeserializer { variant, value: None, }) } else { Err(Error::message("expected tuple or atom")) } } fn deserialize_identifier(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: serde::de::Visitor<'de>, { self.deserialize_any(visitor) } } struct SeqDeserializer<'de> { iter: ListIterator<'de>, } impl<'de> SeqDeserializer<'de> { pub fn new(list: List<'de>) -> Result> { let iter = list.iter(); Ok(SeqDeserializer { iter }) } } impl<'de> serde::de::SeqAccess<'de> for SeqDeserializer<'de> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: serde::de::DeserializeSeed<'de>, { let value = match self.iter.next() { Some(value) => value, None => return Ok(None), }; seed.deserialize(value).map(Some) } } struct MapDeserializer<'de> { len: usize, iter: MapIterator<'de>, value: Option>, } impl<'de> MapDeserializer<'de> { pub fn new(map: Map<'de>) -> Result> { let len = map.size()?; let iter = map.iter()?; Ok(MapDeserializer { len, iter, value: None, }) } } impl<'de> serde::de::MapAccess<'de> for MapDeserializer<'de> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where K: serde::de::DeserializeSeed<'de>, { let (key, value) = match self.iter.next() { Some((key, value)) => (key, value), None => return Ok(None), }; self.value = Some(value); seed.deserialize(key).map(Some) } fn next_value_seed(&mut self, seed: V) -> Result where V: serde::de::DeserializeSeed<'de>, { let value = self.value.take().unwrap(); seed.deserialize(value) } fn size_hint(&self) -> Option { Some(self.len) } } impl serde::de::Error for Error { fn custom(msg: T) -> Self where T: std::fmt::Display, { Error::message(msg.to_string()) } } struct EnumDeserializer<'de> { variant: String, value: Option>, } impl<'de> serde::de::EnumAccess<'de> for EnumDeserializer<'de> { type Error = Error; type Variant = VariantDeserializer<'de>; fn variant_seed(self, seed: V) -> Result<(V::Value, VariantDeserializer<'de>), Error> where V: serde::de::DeserializeSeed<'de>, { let visitor = VariantDeserializer { value: self.value }; seed.deserialize(self.variant.into_deserializer()) .map(|v| (v, visitor)) } } impl<'de> serde::de::IntoDeserializer<'de, Error> for Term<'de> { type Deserializer = Self; fn into_deserializer(self) -> Self::Deserializer { self } } struct VariantDeserializer<'de> { value: Option>, } impl<'de> serde::de::VariantAccess<'de> for VariantDeserializer<'de> { type Error = Error; fn unit_variant(self) -> Result<(), Error> { match self.value { Some(value) => serde::Deserialize::deserialize(value), None => Ok(()), } } fn newtype_variant_seed(self, seed: T) -> Result where T: serde::de::DeserializeSeed<'de>, { match self.value { Some(value) => seed.deserialize(value), None => Err(Error::message("expected newtype variant")), } } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: serde::de::Visitor<'de>, { match self.value { Some(value) if value.is_list() => value.deserialize_seq(visitor), _ => Err(Error::message("expected tuple variant")), } } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: serde::de::Visitor<'de>, { match self.value { Some(value) if value.is_map() => value.deserialize_map(visitor), _ => Err(Error::message("expected struct variant")), } } }