diff --git a/src/de/mod.rs b/src/de/mod.rs index 1dd019134..76d9b24bb 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -16,7 +16,7 @@ use crate::{ error::{Result, SpannedResult}, extensions::Extensions, options::Options, - parse::{NewtypeMode, ParsedByteStr, ParsedStr, Parser, StructType, TupleMode}, + parse::{NewtypeMode, ParsedByteStr, ParsedStr, Parser, ParserCursor, StructType, TupleMode}, }; #[cfg(feature = "std")] @@ -173,7 +173,12 @@ impl<'de> Deserializer<'de> { /// struct and deserializes it accordingly. /// /// This method assumes there is no identifier left. - fn handle_any_struct(&mut self, visitor: V, ident: Option<&str>) -> Result + fn handle_any_struct( + &mut self, + visitor: V, + ident: Option<&str>, + cursor: ParserCursor, + ) -> Result where V: Visitor<'de>, { @@ -185,22 +190,26 @@ impl<'de> Deserializer<'de> { let old_serde_content_newtype = self.serde_content_newtype; self.serde_content_newtype = false; - match ( - self.parser.check_struct_type( - NewtypeMode::NoParensMeanUnit, - if old_serde_content_newtype { - TupleMode::DifferentiateNewtype // separate match on NewtypeOrTuple below - } else { - TupleMode::ImpreciseTupleOrNewtype // Tuple and NewtypeOrTuple match equally - }, - )?, - ident, - ) { + let struct_type = self.parser.check_struct_type( + NewtypeMode::NoParensMeanUnit, + if old_serde_content_newtype { + TupleMode::DifferentiateNewtype // separate match on NewtypeOrTuple below + } else { + TupleMode::ImpreciseTupleOrNewtype // Tuple and NewtypeOrTuple match equally + }, + )?; + + match (struct_type, ident) { (StructType::Unit, Some(ident)) if is_serde_content => { // serde's Content type needs the ident for unit variants visitor.visit_str(ident) } - (StructType::Unit, _) => visitor.visit_unit(), + (StructType::Unit, Some(ident)) => { + self.parser.cursor = cursor; + let enum_access = Enum::new(self, EnumKind::Unit); + visitor.visit_enum(enum_access) + } + (StructType::Unit, None) => visitor.visit_unit(), (_, Some(ident)) if is_serde_content => { // serde's Content type uses a singleton map encoding for enums visitor.visit_map(SerdeEnumContent { @@ -208,10 +217,15 @@ impl<'de> Deserializer<'de> { ident: Some(ident), }) } - (StructType::Named, _) => { + (StructType::Named, None) => { // giving no name results in worse errors but is necessary here self.handle_struct_after_name("", visitor) } + (StructType::Named, Some(ident)) => { + self.parser.cursor = cursor; + let enum_access = Enum::new(self, EnumKind::Struct); + visitor.visit_enum(enum_access) + } (StructType::NewtypeTuple, _) if old_serde_content_newtype => { // deserialize a newtype struct or variant self.parser.consume_char('('); @@ -222,12 +236,28 @@ impl<'de> Deserializer<'de> { result } + (StructType::AnyTuple | StructType::NonNewtypeTuple, Some(indent)) => { + self.parser.cursor = cursor; + let enum_access = Enum::new(self, EnumKind::Tuple); + visitor.visit_enum(enum_access) + } + (StructType::EmptyTuple, Some(indent)) => { + self.parser.cursor = cursor; + // should we use unit ? + let enum_access = Enum::new(self, EnumKind::Tuple); + visitor.visit_enum(enum_access) + } + (StructType::NewtypeTuple, Some(indent)) => { + self.parser.cursor = cursor; + let enum_access = Enum::new(self, EnumKind::NewType); + visitor.visit_enum(enum_access) + } ( StructType::AnyTuple | StructType::EmptyTuple | StructType::NewtypeTuple | StructType::NonNewtypeTuple, - _, + None, ) => { // first argument is technically incorrect, but ignored anyway self.deserialize_tuple(0, visitor) @@ -341,15 +371,17 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { return visitor.visit_f64(core::f64::NAN); } + let parser_save = self.parser.cursor.clone(); + // `skip_identifier` does not change state if it fails if let Some(ident) = self.parser.skip_identifier() { self.parser.skip_ws()?; - return self.handle_any_struct(visitor, Some(ident)); + return self.handle_any_struct(visitor, Some(ident), parser_save); } match self.parser.peek_char_or_eof()? { - '(' => self.handle_any_struct(visitor, None), + '(' => self.handle_any_struct(visitor, None, parser_save), '[' => self.deserialize_seq(visitor), '{' => self.deserialize_map(visitor), '0'..='9' | '+' | '-' | '.' => self.parser.any_number()?.visit(visitor), @@ -744,7 +776,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { { self.newtype_variant = false; - match guard_recursion! { self => visitor.visit_enum(Enum::new(self)) } { + match guard_recursion! { self => visitor.visit_enum(Enum::new(self, EnumKind::Unknown)) } { Ok(value) => Ok(value), Err(Error::NoSuchEnumVariant { expected, @@ -904,13 +936,22 @@ impl<'de, 'a> de::MapAccess<'de> for CommaSeparated<'a, 'de> { } } +enum EnumKind { + Unknown, + Unit, + NewType, + Tuple, + Struct, +} + struct Enum<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, + kind: EnumKind, } impl<'a, 'de> Enum<'a, 'de> { - fn new(de: &'a mut Deserializer<'de>) -> Self { - Enum { de } + fn new(de: &'a mut Deserializer<'de>, kind: EnumKind) -> Self { + Enum { de, kind } } } @@ -934,13 +975,26 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { type Error = Error; fn unit_variant(self) -> Result<()> { - Ok(()) + // todo: consume () if exist ? + match self.kind { + EnumKind::Unknown | EnumKind::Unit => Ok(()), + EnumKind::NewType => Err(Error::ExpectedNamedNewType), + EnumKind::Tuple => Err(Error::ExpectedNamedTuple), + EnumKind::Struct => Err(Error::ExpectedNamedStruct), + } } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { + match self.kind { + EnumKind::Unknown | EnumKind::NewType => {} + EnumKind::Unit => return Err(Error::ExpectedNamedUnit), + EnumKind::Tuple => return Err(Error::ExpectedNamedTuple), + EnumKind::Struct => return Err(Error::ExpectedNamedStruct), + } + let newtype_variant = self.de.last_identifier; self.de.parser.skip_ws()?; @@ -978,6 +1032,13 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { where V: Visitor<'de>, { + match self.kind { + EnumKind::Unknown | EnumKind::Tuple => {} + EnumKind::Unit => return Err(Error::ExpectedNamedUnit), + EnumKind::NewType => return Err(Error::ExpectedNamedNewType), + EnumKind::Struct => return Err(Error::ExpectedNamedStruct), + } + self.de.parser.skip_ws()?; self.de.deserialize_tuple(len, visitor) @@ -987,6 +1048,13 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { where V: Visitor<'de>, { + match self.kind { + EnumKind::Unknown | EnumKind::Struct => {} + EnumKind::Unit => return Err(Error::ExpectedNamedUnit), + EnumKind::Tuple => return Err(Error::ExpectedNamedTuple), + EnumKind::NewType => return Err(Error::ExpectedNamedNewType), + } + let struct_variant = self.de.last_identifier; self.de.parser.skip_ws()?; diff --git a/src/de/value.rs b/src/de/value.rs index 8fd75287e..058ec065a 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -1,5 +1,6 @@ use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec}; use core::fmt; +use std::borrow::Cow; use serde::{ de::{Error, MapAccess, SeqAccess, Visitor}, @@ -214,14 +215,14 @@ impl<'de> Visitor<'de> for ValueVisitor { vec.push(x); } - Ok(Value::Seq(vec)) + Ok(Value::List(vec)) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { - let mut res: Map = Map::new(); + let mut res: Map = Map::new(); #[cfg(feature = "indexmap")] if let Some(cap) = map.size_hint() { @@ -234,6 +235,76 @@ impl<'de> Visitor<'de> for ValueVisitor { Ok(Value::Map(res)) } + + fn visit_enum(self, mut data: A) -> Result + where + A: serde::de::EnumAccess<'de>, + { + // Get the variant name and the VariantAccess + let (variant, variant_access) = data.variant::()?; + + + // Try to extract the value for the variant + use serde::de::VariantAccess; + + let value = if let Ok(v) = variant_access.unit_variant() { + Value::NamedUnit { + name: variant.0.into(), + } + } else if let Ok(v) = variant_access.newtype_variant() { + Value::NamedNewtype { + name: variant.0.into(), + inner: Box::new(v), + } + } else if let Ok(v) = variant_access.tuple_variant(0, ValueVisitor) { + if let Value::Tuple(values) = v { + Value::NamedTuple(variant.0.into(), values) + } else { + return Err(A::Error::custom("Expected Value::Tuple")); + } + } else if let Ok(v) = variant_access.struct_variant(&[], ValueVisitor) { + if let Value::Map(values) = v { + let mut values_new: Map> = Map::new(); + + for e in values { + if let Value::String(k) = e.0 { + values_new.insert(>>::into(k), e.1); + } else { + return Err(A::Error::custom("Expected Value::String for the key")); + } + } + + Value::NamedMap(variant.0.into(), values_new) + } else { + return Err(A::Error::custom("Expected Value::Map")); + } + } else { + // fallback: treat as unit + Value::Unit + }; + + Ok(value) + } +} + +// todo: use id::Deserializer ? +struct Ident(String); + +impl<'de> Deserialize<'de> for Ident { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer + .deserialize_identifier(ValueVisitor) + .and_then(|e| { + if let Value::String(ident) = e { + Ok(Ident(ident)) + } else { + unreachable!() + } + }) + } } #[cfg(test)] @@ -265,7 +336,7 @@ mod tests { fn test_tuples_basic() { assert_eq!( eval("(3, 4.0, 5.0)"), - Value::Seq(vec![ + Value::List(vec![ Value::Number(Number::U8(3)), Value::Number(Number::F32(4.0.into())), Value::Number(Number::F32(5.0.into())), @@ -277,7 +348,7 @@ mod tests { fn test_tuples_ident() { assert_eq!( eval("(true, 3, 4, 5.0)"), - Value::Seq(vec![ + Value::List(vec![ Value::Bool(true), Value::Number(Number::U8(3)), Value::Number(Number::U8(4)), @@ -306,7 +377,7 @@ mod tests { fn test_floats() { assert_eq!( eval("(inf, -inf, NaN)"), - Value::Seq(vec![ + Value::List(vec![ Value::Number(Number::new(core::f32::INFINITY)), Value::Number(Number::new(core::f32::NEG_INFINITY)), Value::Number(Number::new(core::f32::NAN)), @@ -333,7 +404,7 @@ mod tests { ), ])" ), - Value::Option(Some(Box::new(Value::Seq(vec![ + Value::Option(Some(Box::new(Value::List(vec![ Value::Map( vec![ ( diff --git a/src/error.rs b/src/error.rs index bbe4dd7f1..f5725e769 100644 --- a/src/error.rs +++ b/src/error.rs @@ -117,6 +117,11 @@ pub enum Error { ExpectedRawValue, ExceededRecursionLimit, ExpectedStructName(String), + + ExpectedNamedUnit, + ExpectedNamedNewType, + ExpectedNamedTuple, + ExpectedNamedStruct, } impl fmt::Display for SpannedError { @@ -293,6 +298,10 @@ impl fmt::Display for Error { "Expected the explicit struct name {}, but none was found", Identifier(name) ), + Error::ExpectedNamedUnit => write!(f, "ExpectedNamedUnit"), + Error::ExpectedNamedNewType => write!(f, "ExpectedNamedNewType"), + Error::ExpectedNamedTuple => write!(f, "ExpectedNamedTuple"), + Error::ExpectedNamedStruct => write!(f, "ExpectedNamedStruct"), } } } diff --git a/src/lib.rs b/src/lib.rs index bbc43c9f6..2a610acec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(warnings)] #![deny(clippy::correctness)] #![deny(clippy::suspicious)] #![deny(clippy::complexity)] diff --git a/src/parse.rs b/src/parse.rs index 91d7be7e3..6583cad80 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -63,7 +63,7 @@ pub struct Parser<'a> { /// Bits set according to the [`Extensions`] enum. pub exts: Extensions, src: &'a str, - cursor: ParserCursor, + pub cursor: ParserCursor, prev_cursor: ParserCursor, } diff --git a/src/ser/value.rs b/src/ser/value.rs index 87fdbce83..eb7a80a7c 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -1,4 +1,4 @@ -use serde::ser::{Serialize, Serializer}; +use serde::ser::{Serialize, SerializeStruct, SerializeTuple, SerializeTupleStruct, Serializer}; use crate::value::Value; @@ -7,17 +7,63 @@ impl Serialize for Value { where S: Serializer, { - match *self { - Value::Bool(b) => serializer.serialize_bool(b), - Value::Char(c) => serializer.serialize_char(c), - Value::Map(ref m) => Serialize::serialize(m, serializer), - Value::Number(ref number) => Serialize::serialize(number, serializer), - Value::Option(Some(ref o)) => serializer.serialize_some(o.as_ref()), + match self { + Value::Bool(b) => serializer.serialize_bool(*b), + Value::Char(c) => serializer.serialize_char(*c), + Value::Map(m) => Serialize::serialize(m, serializer), + Value::Number(number) => Serialize::serialize(number, serializer), + Value::Option(Some(o)) => serializer.serialize_some(o.as_ref()), Value::Option(None) => serializer.serialize_none(), - Value::String(ref s) => serializer.serialize_str(s), - Value::Bytes(ref b) => serializer.serialize_bytes(b), - Value::Seq(ref s) => Serialize::serialize(s, serializer), + Value::String(s) => serializer.serialize_str(s), + Value::Bytes(b) => serializer.serialize_bytes(b), + Value::List(s) => Serialize::serialize(s, serializer), Value::Unit => serializer.serialize_unit(), + Value::NamedMap(name, map) => { + // serializer.serialize_struct(name, len) + // serializer.serialize_struct_variant(name, variant_index, variant, len) + + // serializer.serialize_newtype_struct(name, value) + // serializer.serialize_newtype_variant(name, variant_index, variant, value) + + // serializer.serialize_unit_struct(name) + // serializer.serialize_unit_variant(name, variant_index, variant) + + // serializer.serialize_map(len) + + // serializer.serialize_tuple(len) + // serializer.serialize_tuple_struct(name, len) + // serializer.serialize_tuple_variant(name, variant_index, variant, len) + + // https://github.com/serde-rs/json/blob/master/src/value/ser.rs + + match name { + std::borrow::Cow::Borrowed(a) => { + let mut state = serializer.serialize_struct(a, map.len())?; + + for (k, v) in &map.0 { + match k { + std::borrow::Cow::Borrowed(a) => { + state.serialize_field(a, &v)?; + } + std::borrow::Cow::Owned(_) => todo!(), + } + } + + state.end() + } + std::borrow::Cow::Owned(_) => todo!(), + } + } + Value::Tuple(vec) => { + let mut state = serializer.serialize_tuple(vec.len())?; + + for v in vec { + state.serialize_element(&v)?; + } + + state.end() + } + _ => todo!(), } } } diff --git a/src/value/map.rs b/src/value/map.rs index 4bedba4c6..53d7be01b 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -15,16 +15,22 @@ use super::Value; /// [`IndexMap`](indexmap::IndexMap) internally. /// The latter can be used by enabling the `indexmap` feature. This can be used /// to preserve the order of the parsed map. -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(transparent)] -pub struct Map(pub(crate) MapInner); +pub struct Map(pub(crate) MapInner); #[cfg(not(feature = "indexmap"))] -type MapInner = alloc::collections::BTreeMap; +type MapInner = alloc::collections::BTreeMap; #[cfg(feature = "indexmap")] -type MapInner = indexmap::IndexMap; +type MapInner = indexmap::IndexMap; -impl Map { +impl Default for Map { + fn default() -> Self { + Self(Default::default()) + } +} + +impl Map { /// Creates a new, empty [`Map`]. #[must_use] pub fn new() -> Self { @@ -45,23 +51,23 @@ impl Map { /// Immutably looks up an element by its `key`. #[must_use] - pub fn get(&self, key: &Value) -> Option<&Value> { + pub fn get(&self, key: &Key) -> Option<&Value> { self.0.get(key) } /// Mutably looks up an element by its `key`. - pub fn get_mut(&mut self, key: &Value) -> Option<&mut Value> { + pub fn get_mut(&mut self, key: &Key) -> Option<&mut Value> { self.0.get_mut(key) } /// Inserts a new element, returning the previous element with this `key` if /// there was any. - pub fn insert(&mut self, key: impl Into, value: impl Into) -> Option { + pub fn insert(&mut self, key: impl Into, value: impl Into) -> Option { self.0.insert(key.into(), value.into()) } /// Removes an element by its `key`. - pub fn remove(&mut self, key: &Value) -> Option { + pub fn remove(&mut self, key: &Key) -> Option { #[cfg(feature = "indexmap")] { self.0.shift_remove(key) @@ -74,19 +80,19 @@ impl Map { /// Iterate all key-value pairs. #[must_use] - pub fn iter(&self) -> impl DoubleEndedIterator { + pub fn iter(&self) -> impl DoubleEndedIterator { self.0.iter() } /// Iterate all key-value pairs mutably. #[must_use] - pub fn iter_mut(&mut self) -> impl DoubleEndedIterator { + pub fn iter_mut(&mut self) -> impl DoubleEndedIterator { self.0.iter_mut() } /// Iterate all keys. #[must_use] - pub fn keys(&self) -> impl DoubleEndedIterator { + pub fn keys(&self) -> impl DoubleEndedIterator { self.0.keys() } @@ -110,39 +116,39 @@ impl Map { /// The elements are visited in iteration order. pub fn retain(&mut self, keep: F) where - F: FnMut(&Value, &mut Value) -> bool, + F: FnMut(&Key, &mut Value) -> bool, { self.0.retain(keep); } } -impl Index<&Value> for Map { +impl Index<&Key> for Map { type Output = Value; #[allow(clippy::expect_used)] - fn index(&self, index: &Value) -> &Self::Output { + fn index(&self, index: &Key) -> &Self::Output { self.get(index).expect("no entry found for key") } } -impl IndexMut<&Value> for Map { +impl IndexMut<&Key> for Map { #[allow(clippy::expect_used)] - fn index_mut(&mut self, index: &Value) -> &mut Self::Output { + fn index_mut(&mut self, index: &Key) -> &mut Self::Output { self.get_mut(index).expect("no entry found for key") } } -impl IntoIterator for Map { - type Item = (Value, Value); +impl IntoIterator for Map { + type Item = (Key, Value); - type IntoIter = ::IntoIter; + type IntoIter = as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } -impl, V: Into> FromIterator<(K, V)> for Map { +impl, V: Into> FromIterator<(K, V)> for Map { fn from_iter>(iter: T) -> Self { Map(iter .into_iter() @@ -152,28 +158,28 @@ impl, V: Into> FromIterator<(K, V)> for Map { } /// Note: equality is only given if both values and order of values match -impl PartialEq for Map { - fn eq(&self, other: &Map) -> bool { +impl PartialEq for Map { + fn eq(&self, other: &Map) -> bool { self.cmp(other).is_eq() } } /// Note: equality is only given if both values and order of values match -impl Eq for Map {} +impl Eq for Map {} -impl PartialOrd for Map { - fn partial_cmp(&self, other: &Map) -> Option { +impl PartialOrd for Map { + fn partial_cmp(&self, other: &Map) -> Option { Some(self.cmp(other)) } } -impl Ord for Map { - fn cmp(&self, other: &Map) -> Ordering { +impl Ord for Map { + fn cmp(&self, other: &Map) -> Ordering { self.iter().cmp(other.iter()) } } -impl Hash for Map { +impl Hash for Map { fn hash(&self, state: &mut H) { self.iter().for_each(|x| x.hash(state)); } @@ -258,7 +264,7 @@ mod tests { } #[cfg(feature = "std")] - fn assert_same_hash(a: &Map, b: &Map) { + fn assert_same_hash(a: &Map, b: &Map) { use core::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; diff --git a/src/value/mod.rs b/src/value/mod.rs index 9735b1af0..2c0fc8dfc 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -2,9 +2,13 @@ use alloc::{borrow::Cow, boxed::Box, format, string::String, vec::Vec}; use core::{cmp::Eq, hash::Hash}; +use std::{borrow::ToOwned, string::ToString}; use serde::{ - de::{DeserializeOwned, DeserializeSeed, Deserializer, MapAccess, SeqAccess, Visitor}, + de::{ + DeserializeOwned, DeserializeSeed, Deserializer, EnumAccess, MapAccess, SeqAccess, + VariantAccess, Visitor, + }, forward_to_deserialize_any, }; @@ -21,15 +25,34 @@ pub use raw::RawValue; #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum Value { + /// Can represent a struct with no field, or the Unit type + Unit, Bool(bool), Char(char), - Map(Map), Number(Number), - Option(Option>), String(String), Bytes(Vec), - Seq(Vec), - Unit, + Option(Option>), + List(Vec), + /// Can be a struct + Map(Map), + Tuple(Vec), + + /// Can be either an empty enum or an empty unit variant + NamedUnit { + name: Cow<'static, str>, + }, + /// Struct + Newtype(Box), + /// Enum or struct + NamedNewtype { + name: Cow<'static, str>, + inner: Box, + }, + /// Enum or struct + NamedMap(Cow<'static, str>, Map>), + /// Enum or struct + NamedTuple(Cow<'static, str>, Vec), } impl From for Value { @@ -50,8 +73,8 @@ impl, V: Into> FromIterator<(K, V)> for Value { } } -impl From for Value { - fn from(value: Map) -> Self { +impl From> for Value { + fn from(value: Map) -> Self { Self::Map(value) } } @@ -95,7 +118,7 @@ impl From<&'static [u8; N]> for Value { impl> FromIterator for Value { fn from_iter>(iter: I) -> Self { - Self::Seq(iter.into_iter().map(Into::into).collect()) + Self::List(iter.into_iter().map(Into::into).collect()) } } @@ -175,7 +198,7 @@ impl<'de> Deserializer<'de> for Value { Value::Option(None) => visitor.visit_none(), Value::String(s) => visitor.visit_string(s), Value::Bytes(b) => visitor.visit_byte_buf(b), - Value::Seq(mut seq) => { + Value::List(mut seq) => { let old_len = seq.len(); seq.reverse(); @@ -191,6 +214,38 @@ impl<'de> Deserializer<'de> for Value { } } Value::Unit => visitor.visit_unit(), + Value::Tuple(mut seq) => { + let old_len = seq.len(); + + seq.reverse(); + let value = visitor.visit_seq(SeqAccessor { seq: &mut seq })?; + + if seq.is_empty() { + Ok(value) + } else { + Err(Error::ExpectedDifferentLength { + expected: format!("a sequence of length {}", old_len - seq.len()), + found: old_len, + }) + } + } + Value::Newtype(value) => visitor.visit_newtype_struct(*value), + Value::NamedUnit { name } => visitor.visit_enum(EnumAccessor { + variant: name.to_string(), + value: Value::NamedUnit { name }, + }), + Value::NamedNewtype { name, inner } => visitor.visit_enum(EnumAccessor { + variant: name.to_string(), + value: Value::NamedNewtype { name, inner }, + }), + Value::NamedMap(name, map) => visitor.visit_enum(EnumAccessor { + variant: name.to_string(), + value: Value::NamedMap(name, map), + }), + Value::NamedTuple(name, values) => visitor.visit_enum(EnumAccessor { + variant: name.to_string(), + value: Value::NamedTuple(name, values), + }), } } } @@ -255,12 +310,101 @@ impl<'a, 'de> MapAccess<'de> for MapAccessor<'a> { } } +struct EnumAccessor { + variant: String, + value: Value, +} + +impl<'de> EnumAccess<'de> for EnumAccessor { + type Error = Error; + + type Variant = VariantAccessor; + + fn variant_seed( + self, + seed: V, + ) -> core::result::Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>, + { + let v = seed.deserialize(Value::String(self.variant))?; + Ok((v, VariantAccessor { value: self.value })) + } +} + +struct VariantAccessor { + value: Value, +} + +impl<'a, 'de> VariantAccess<'de> for VariantAccessor { + type Error = Error; + + fn unit_variant(self) -> core::result::Result<(), Self::Error> { + if let Value::NamedUnit { .. } = self.value { + Ok(()) + } else { + Err(Error::ExpectedUnit) + } + } + + fn newtype_variant_seed(self, seed: T) -> core::result::Result + where + T: DeserializeSeed<'de>, + { + if let Value::NamedNewtype { inner, .. } = self.value { + seed.deserialize(*inner) + } else { + Err(Error::ExpectedNamedNewType) + } + } + + fn tuple_variant(self, len: usize, visitor: V) -> core::result::Result + where + V: Visitor<'de>, + { + if let Value::NamedTuple(_, mut items) = self.value { + if items.len() != len { + return Err(Error::ExpectedDifferentLength { + expected: format!("tuple of length {}", len), + found: items.len(), + }); + } + visitor.visit_seq(SeqAccessor { seq: &mut items }) + } else { + Err(Error::ExpectedNamedTuple) + } + } + + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> core::result::Result + where + V: Visitor<'de>, + { + if let Value::NamedMap(_, mut map) = self.value { + let mut items: Vec<(Value, Value)> = map + .into_iter() + .map(|e| (Value::String(e.0.to_string()), e.1)) + .collect(); + visitor.visit_map(MapAccessor { + items: &mut items, + value: None, + }) + } else { + Err(Error::ExpectedNamedStruct) + } + } +} + #[cfg(test)] mod tests { use alloc::{collections::BTreeMap, vec}; use core::fmt::Debug; + use std::dbg; - use serde::Deserialize; + use serde::{Deserialize, Serialize}; use super::*; @@ -272,6 +416,7 @@ mod tests { let direct: T = from_str(s).unwrap(); let value: Value = from_str(s).unwrap(); + dbg!(&value); let de = T::deserialize(value.clone()).unwrap(); assert_eq!(direct, de, "Deserialization for {:?} is not the same", s); @@ -411,12 +556,12 @@ mod tests { } #[test] - fn seq() { + fn list() { assert_same::>("[1.0, 2.0, 3.0, 4.0]"); assert_eq!( Value::from([-1_i8, 2, -3].as_slice()), - Value::Seq(vec![ + Value::List(vec![ Value::from(-1_i8), Value::from(2_i8), Value::from(-3_i8) @@ -424,7 +569,7 @@ mod tests { ); assert_eq!( Value::from(vec![-1_i8, 2, -3]), - Value::Seq(vec![ + Value::List(vec![ Value::from(-1_i8), Value::from(2_i8), Value::from(-3_i8) @@ -432,7 +577,7 @@ mod tests { ); assert_eq!( Value::from_iter([-1_i8, 2, -3]), - Value::Seq(vec![ + Value::List(vec![ Value::from(-1_i8), Value::from(2_i8), Value::from(-3_i8) @@ -501,4 +646,176 @@ mod tests { Value::from('🦀') ); } + + #[test] + fn unit_struct_without_brace() { + #[derive(Debug, Deserialize, PartialEq)] + struct A; + assert_same::("()"); + } + + #[test] + fn unit_struct() { + #[derive(Debug, Deserialize, PartialEq)] + struct A {}; + assert_same::("A()"); + } + + #[test] + fn unit_enum() { + #[derive(Debug, Deserialize, PartialEq)] + enum A { + A, + } + + assert_same::("A"); + } + + #[test] + fn new_type_struct() { + #[derive(Debug, Deserialize, PartialEq)] + struct A(i32); + + assert_same::("A(1)"); + } + + #[test] + // panic + fn new_type_enum() { + #[derive(Debug, Deserialize, PartialEq)] + enum A { + A(i32), + } + + assert_same::("A(1)"); + } + + #[test] + fn tuple_struct() { + #[derive(Debug, Deserialize, PartialEq)] + struct A(i32, String); + assert_same::("A(1, \"hello\")"); + } + + #[test] + // panic + fn tuple_enum() { + #[derive(Debug, Deserialize, PartialEq)] + enum A { + A(i32, String), + } + + assert_same::("A(1, \"hello\")"); + } + + #[test] + fn r#struct() { + #[derive(Debug, Deserialize, PartialEq)] + struct A { + name: String, + age: i32, + } + + assert_same::("A(name: \"Alice\", age: 30,)"); + } + + #[test] + // panic + fn r#enum() { + #[derive(Debug, Deserialize, PartialEq)] + enum A { + A { name: String, age: i32 }, + } + + assert_same::("A(name: \"Alice\", age: 30,)"); + } + + #[ignore = ""] + #[test] + fn test() { + use std::collections::HashMap; + use std::println; + #[derive(Serialize)] + enum Enum { + A, + B, + } + + #[derive(Serialize)] + struct Struct { + e: Enum, + h: HashMap, + } + + let v = Struct { + e: Enum::A, + h: [("hello".into(), "world".into())].into_iter().collect(), + }; + + let ron_str = crate::to_string(&v).unwrap(); + + println!("{}", ron_str); + + let value = crate::from_str::(&ron_str).unwrap(); + + dbg!(&value); + // println!("{:?}", value); + + let ron_str2 = crate::to_string(&value).unwrap(); + + println!("{}", ron_str2); + + assert_eq!(ron_str, ron_str2); + } + + #[ignore = ""] + #[test] + fn test2() { + use std::collections::HashMap; + use std::println; + + #[derive(Serialize)] + enum B { + A(Option, i32), + B, + } + + #[derive(Serialize)] + struct A { + a: B, + } + + let v = A { + a: B::A(Some("a".into()), 0), + }; + + let ron_str = crate::to_string(&v).unwrap(); + + println!("{}", ron_str); + + let value = crate::from_str::(&ron_str).unwrap(); + + println!("{:?}", value); + + let ron_str2 = crate::to_string(&value).unwrap(); + + println!("{}", ron_str2); + + assert_eq!(ron_str, ron_str2); + } + + #[ignore = ""] + #[test] + fn test3() { + use std::println; + + #[derive(Serialize)] + struct A; + + let v = A; + + let ron_str = crate::to_string(&v).unwrap(); + + println!("{}", ron_str); + } } diff --git a/tests/238_array.rs b/tests/238_array.rs index 719473994..dd1a9b856 100644 --- a/tests/238_array.rs +++ b/tests/238_array.rs @@ -16,7 +16,7 @@ fn test_array() { let value: Value = ron::from_str(&ser).unwrap(); assert_eq!( value, - Value::Seq(vec![ + Value::List(vec![ Value::Number(Number::U8(1)), Value::Number(Number::U8(2)), Value::Number(Number::U8(3)), @@ -45,7 +45,7 @@ fn test_array() { let value: Value = ron::from_str(&ser).unwrap(); assert_eq!( value, - Value::Seq(vec![ + Value::List(vec![ Value::Number(Number::U8(1)), Value::Number(Number::U8(2)), Value::Number(Number::U8(3)), diff --git a/tests/465_no_comment_char_value.rs b/tests/465_no_comment_char_value.rs index 4d77f0ad1..d14bf7458 100644 --- a/tests/465_no_comment_char_value.rs +++ b/tests/465_no_comment_char_value.rs @@ -4,10 +4,12 @@ fn value_deserialises_r_name() { // searcher reads into the char and then finds a weird comment starter there assert_eq!( ron::from_str("A('/')"), - Ok(ron::Value::Seq(vec![ron::Value::Char('/')])) + Ok(ron::Value::List(vec![ron::Value::Char('/')])) ); assert_eq!( ron::from_str("A(\"/\")"), - Ok(ron::Value::Seq(vec![ron::Value::String(String::from("/"))])) + Ok(ron::Value::List(vec![ron::Value::String(String::from( + "/" + ))])) ); } diff --git a/tests/465_r_name_value.rs b/tests/465_r_name_value.rs index d6a63bc50..5ecdc30d8 100644 --- a/tests/465_r_name_value.rs +++ b/tests/465_r_name_value.rs @@ -1,10 +1,10 @@ #[test] fn value_deserialises_r_name() { assert_eq!(ron::from_str("r"), Ok(ron::Value::Unit)); - assert_eq!(ron::from_str("r()"), Ok(ron::Value::Seq(vec![]))); + assert_eq!(ron::from_str("r()"), Ok(ron::Value::List(vec![]))); assert_eq!( ron::from_str("r(42)"), - Ok(ron::Value::Seq(vec![ron::Value::Number( + Ok(ron::Value::List(vec![ron::Value::Number( ron::value::Number::U8(42) )])) ); diff --git a/tests/465_unwrap_some_newtype_variant_value.rs b/tests/465_unwrap_some_newtype_variant_value.rs index ea459bd11..7432f9f1e 100644 --- a/tests/465_unwrap_some_newtype_variant_value.rs +++ b/tests/465_unwrap_some_newtype_variant_value.rs @@ -23,7 +23,7 @@ fn deserialise_value_with_unwrap_some_newtype_variant() { ); assert_eq!( ron::from_str("#![enable(unwrap_variant_newtypes)] Some(42, true)"), - Ok(ron::Value::Option(Some(Box::new(ron::Value::Seq(vec![ + Ok(ron::Value::Option(Some(Box::new(ron::Value::List(vec![ ron::Value::Number(ron::value::Number::U8(42)), ron::Value::Bool(true) ]))))), diff --git a/tests/value.rs b/tests/value.rs index 11efebaef..f19ede8a7 100644 --- a/tests/value.rs +++ b/tests/value.rs @@ -111,14 +111,14 @@ fn byte_string() { #[test] fn seq() { - let seq = Value::Seq(vec![ + let seq = Value::List(vec![ Value::Number(Number::U8(1)), Value::Number(Number::new(2f32)), ]); assert_eq!(ron::to_string(&seq).unwrap(), "[1,2.0]"); assert_eq!("[1, 2.0]".parse(), Ok(seq)); - let err = Value::Seq(vec![Value::Number(Number::new(1))]) + let err = Value::List(vec![Value::Number(Number::new(1))]) .into_rust::<[i32; 2]>() .unwrap_err(); @@ -130,7 +130,7 @@ fn seq() { } ); - let err = Value::Seq(vec![ + let err = Value::List(vec![ Value::Number(Number::new(1)), Value::Number(Number::new(2)), Value::Number(Number::new(3)),