diff --git a/Cargo.toml b/Cargo.toml index d2b05ba2..41a5891f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ron" -version = "0.1.4" +version = "0.1.5" license = "MIT/Apache-2.0" keywords = ["parser", "serde", "serialization"] authors = [ diff --git a/src/value.rs b/src/value.rs index 3fca393c..acefb983 100644 --- a/src/value.rs +++ b/src/value.rs @@ -4,6 +4,10 @@ use std::cmp::{Eq, Ordering}; use std::collections::BTreeMap; use std::hash::{Hash, Hasher}; +use serde::de::{DeserializeSeed, Deserializer, MapAccess, SeqAccess, Visitor}; + +use de::{Error as RonError, Result}; + /// A wrapper for `f64` which guarantees that the inner value /// is finite and thus implements `Eq`, `Hash` and `Ord`. #[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] @@ -51,3 +55,151 @@ pub enum Value { Seq(Vec), Unit, } + +/// Deserializer implementation for RON `Value`. +/// This does not support enums (because `Value` doesn't store them). +impl<'de> Deserializer<'de> for Value { + type Error = RonError; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + Value::Bool(b) => visitor.visit_bool(b), + Value::Char(c) => visitor.visit_char(c), + Value::Map(m) => visitor.visit_map(Map { + keys: m.keys().cloned().rev().collect(), + values: m.values().cloned().rev().collect(), + }), + Value::Number(n) => visitor.visit_f64(n.get()), + Value::Option(Some(o)) => visitor.visit_some(*o), + Value::Option(None) => visitor.visit_none(), + Value::String(s) => visitor.visit_string(s), + Value::Seq(mut seq) => { + seq.reverse(); + + visitor.visit_seq(Seq { seq }) + } + Value::Unit => visitor.visit_unit(), + } + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes + byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +struct Map { + keys: Vec, + values: Vec, +} + +impl<'de> MapAccess<'de> for Map { + type Error = RonError; + + fn next_key_seed(&mut self, seed: K) -> Result> + where + K: DeserializeSeed<'de>, + { + // The `Vec` is reversed, so we can pop to get the originally first element + self.keys + .pop() + .map_or(Ok(None), |v| seed.deserialize(v).map(Some)) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, + { + // The `Vec` is reversed, so we can pop to get the originally first element + self.values + .pop() + .map(|v| seed.deserialize(v)) + .expect("Contract violation") + } +} + +struct Seq { + seq: Vec, +} + +impl<'de> SeqAccess<'de> for Seq { + type Error = RonError; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: DeserializeSeed<'de>, + { + // The `Vec` is reversed, so we can pop to get the originally first element + self.seq + .pop() + .map_or(Ok(None), |v| seed.deserialize(v).map(Some)) + } +} + +#[cfg(test)] +mod tests { + use std::fmt::Debug; + use serde::Deserialize; + use super::*; + + fn assert_same<'de, T>(s: &'de str) + where + T: Debug + Deserialize<'de> + PartialEq, + { + use de::from_str; + + let direct: T = from_str(s).unwrap(); + let value: Value = from_str(s).unwrap(); + let value = T::deserialize(value).unwrap(); + + assert_eq!(direct, value, "Deserialization for {:?} is not the same", s); + } + + #[test] + fn boolean() { + assert_same::("true"); + assert_same::("false"); + } + + #[test] + fn float() { + assert_same::("0.123"); + assert_same::("-4.19"); + } + + #[test] + fn char() { + assert_same::("'4'"); + assert_same::("'c'"); + } + + #[test] + fn map() { + assert_same::>( + "{ +'a': \"Hello\", +'b': \"Bye\", + }", + ); + } + + #[test] + fn option() { + assert_same::>("Some('a')"); + assert_same::>("None"); + } + + #[test] + fn seq() { + assert_same::>("[1.0, 2.0, 3.0, 4.0]"); + } + + #[test] + fn unit() { + assert_same::<()>("()"); + } +}