use std::collections::{hash_map, HashMap}; use serde::de::{ self, DeserializeSeed, EnumAccess, Error as DeError, MapAccess, SeqAccess, VariantAccess, Visitor, }; use serde::Deserialize; use crate::debug as fmtdebug; use crate::dec::*; use crate::serde::error::{Error, Result}; /// Serde deserializer for nettext pub struct Deserializer<'de, 'a>(Term<'de, 'a>); impl<'de, 'a> Deserializer<'de, 'a> { pub fn from_term(input: &'a Term<'de, 'a>) -> Deserializer<'de, 'a> { Deserializer(Term(input.0.mkref())) } } /// Deserialize nettext from bytes pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result where T: Deserialize<'a>, { let term = decode(s)?; let mut deserializer = Deserializer::from_term(&term); T::deserialize(&mut deserializer) } /// Deserialize nettext from decoded term pub fn from_term<'a, T>(term: &'a Term<'a, 'a>) -> Result where T: Deserialize<'a>, { let mut deserializer = Deserializer::from_term(term); T::deserialize(&mut deserializer) } // ---- impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de, 'a> { type Error = Error; fn deserialize_any(self, _visitor: V) -> Result where V: Visitor<'de>, { Err(Error::custom(format!( "deserialize_any not supported, at: `{}`", self.0 ))) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { let value = match self.0.string()? { "true" => true, "false" => false, _ => return Err(Error::custom("Invalid boolean litteral")), }; visitor.visit_bool(value) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i8(self.0.string()?.parse()?) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i16(self.0.string()?.parse()?) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i32(self.0.string()?.parse()?) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i64(self.0.string()?.parse()?) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u8(self.0.string()?.parse()?) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u16(self.0.string()?.parse()?) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u32(self.0.string()?.parse()?) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u64(self.0.string()?.parse()?) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_f32(self.0.string()?.parse()?) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_f64(self.0.string()?.parse()?) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { let s = String::from_utf8(self.0.bytes()?)?; let mut chars = s.chars(); let c = chars .next() .ok_or_else(|| Error::custom("invalid char: empty string"))?; if chars.next().is_some() { Err(Error::custom("invalid char: too many chars")) } else { visitor.visit_char(c) } } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { let s = String::from_utf8(self.0.bytes()?)?; visitor.visit_string(s) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_byte_buf(self.0.bytes()?) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_byte_buf(self.0.bytes()?) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { if self.0.dict_of::<0, &[u8]>([], false).is_ok() { visitor.visit_none() } else { visitor.visit_some(self) } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { if self.0.dict_of::<0, &[u8]>([], false).is_ok() { visitor.visit_unit() } else { Err(Error::custom(format!( "Expected unit, got: `{}`", fmtdebug(self.0.raw()) ))) } } fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { if self.0.string()? == name { visitor.visit_unit() } else { Err(Error::custom(format!( "Expected {}, got: `{}`", name, fmtdebug(self.0.raw()) ))) } } fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { let [variant, args] = self.0.seq_of_first()?; if variant.string()? == name { visitor.visit_newtype_struct(&mut Deserializer(args)) } else { Err(Error::custom(format!( "Expected {}, got: `{}`", name, fmtdebug(variant.raw()) ))) } } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_seq(&mut Seq(&self.0.list()?)) } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_seq(&mut Seq(&self.0.seq())) } fn deserialize_tuple_struct( self, name: &'static str, _len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { let [variant, args] = self.0.seq_of_first()?; if variant.string()? == name { visitor.visit_seq(&mut Seq(&args.seq())) } else { Err(Error::custom(format!( "Expected {}, got: `{}`", name, fmtdebug(variant.raw()) ))) } } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_map(&mut Dict::from_term(&self.0)?) } fn deserialize_struct( self, name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let [variant, data] = self.0.seq_of()?; if variant.string()? != name { return Err(Error::custom(format!( "Expected {}, got: `{}`", name, fmtdebug(variant.raw()) ))); } Deserializer(data).deserialize_map(visitor) } fn deserialize_enum( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_enum(Enum(&self.0)) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { let s = self.0.string()?; match s.split_once('.') { Some((_a, b)) => visitor.visit_borrowed_str(b), None => visitor.visit_borrowed_str(s), } } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_any(visitor) } } pub struct Seq<'de, 'a>(&'a [Term<'de, 'a>]); impl<'de, 'a> SeqAccess<'de> for &'a mut Seq<'de, 'a> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: DeserializeSeed<'de>, { // Check if there are no more elements. if self.0.is_empty() { return Ok(None); } let first = Term(self.0[0].0.mkref()); self.0 = &self.0[1..]; seed.deserialize(&mut Deserializer::from_term(&first)) .map(Some) } } pub struct Dict<'de, 'a>( &'a HashMap<&'de [u8], AnyTerm<'de, 'a>>, Option<&'de [u8]>, hash_map::Keys<'a, &'de [u8], AnyTerm<'de, 'a>>, ); impl<'de, 'a> Dict<'de, 'a> { fn from_term(t: &'a Term<'de, 'a>) -> Result> { match t.0.mkref() { AnyTerm::DictRef(_, d) => Ok(Dict(d, None, d.keys())), _ => Err(Error::custom("expected a DICT")), } } } impl<'de, 'a> MapAccess<'de> for &'a mut Dict<'de, 'a> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: DeserializeSeed<'de>, { match self.2.next() { None => Ok(None), Some(k) => { self.1 = Some(k); seed.deserialize(&mut Deserializer(Term(AnyTerm::Str(k)))) .map(Some) } } } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { let k = self .1 .ok_or_else(|| Error::custom("invald mapaccess order"))?; let v = self .0 .get(k) .ok_or_else(|| Error::custom("invald mapaccess order"))?; seed.deserialize(&mut Deserializer(Term(v.mkref()))) } } // ---- struct Enum<'de, 'a>(&'a Term<'de, 'a>); impl<'de, 'a> EnumAccess<'de> for Enum<'de, 'a> { type Error = Error; type Variant = Self; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { let variant = &self.0.seq()[0]; let variant = seed.deserialize(&mut Deserializer(Term(variant.0.mkref())))?; Ok((variant, self)) } } impl<'de, 'a> VariantAccess<'de> for Enum<'de, 'a> { type Error = Error; fn unit_variant(self) -> Result<()> { if self.0.seq().len() > 1 { Err(Error::custom("Spurrious data in unit variant")) } else { Ok(()) } } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { let [_, rest] = self.0.seq_of_first()?; seed.deserialize(&mut Deserializer(rest)) } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { let [_, rest] = self.0.seq_of_first()?; visitor.visit_seq(&mut Seq(&rest.seq())) } fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result where V: Visitor<'de>, { let [_, rest] = self.0.seq_of_first()?; visitor.visit_map(&mut Dict::from_term(&rest)?) } }