From 180f6618d2f53240eed1a2ece0b3ff2af7309214 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Sat, 23 Nov 2024 21:12:26 +0100 Subject: [PATCH 01/13] modif value type --- src/de/value.rs | 8 +- src/ser/value.rs | 57 +++++++++++- src/value/map.rs | 66 +++++++------- src/value/mod.rs | 88 ++++++++++++++++--- tests/238_array.rs | 4 +- tests/465_no_comment_char_value.rs | 4 +- tests/465_r_name_value.rs | 4 +- .../465_unwrap_some_newtype_variant_value.rs | 2 +- tests/value.rs | 6 +- 9 files changed, 183 insertions(+), 56 deletions(-) diff --git a/src/de/value.rs b/src/de/value.rs index 8fd75287e..a9835e5c7 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -214,7 +214,7 @@ 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 @@ -265,7 +265,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 +277,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)), @@ -333,7 +333,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/ser/value.rs b/src/ser/value.rs index 87fdbce83..05c43015b 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; @@ -16,8 +16,61 @@ impl Serialize for Value { 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::List(ref s) => Serialize::serialize(s, serializer), Value::Unit => serializer.serialize_unit(), + Value::Struct(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 { + Some(name) => { + let mut state = serializer.serialize_struct("", map.len())?; + + for (k, v) in map { + state.serialize_field(&k, &v)?; + } + + state.end() + } + None => { + todo!() + } + } + } + Value::Tuple(name, vec) => match name { + Some(name) => { + let mut state = serializer.serialize_tuple_struct("", vec.len())?; + + for v in vec { + state.serialize_field(&v)?; + } + + state.end() + } + None => { + let mut state = serializer.serialize_tuple(vec.len())?; + + for v in vec { + state.serialize_element(&v)?; + } + + state.end() + } + }, } } } diff --git a/src/value/map.rs b/src/value/map.rs index 4bedba4c6..937f35273 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..2478d2dd2 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -23,12 +23,14 @@ pub use raw::RawValue; pub enum Value { Bool(bool), Char(char), - Map(Map), + Map(Map), + Struct(Option, Map), Number(Number), Option(Option>), String(String), Bytes(Vec), - Seq(Vec), + List(Vec), + Tuple(Option, Vec), Unit, } @@ -50,8 +52,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 +97,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 +177,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(); @@ -260,7 +262,7 @@ mod tests { use alloc::{collections::BTreeMap, vec}; use core::fmt::Debug; - use serde::Deserialize; + use serde::{Deserialize, Serialize}; use super::*; @@ -416,7 +418,7 @@ mod tests { 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 +426,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 +434,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 +503,70 @@ mod tests { Value::from('🦀') ); } + + #[test] + fn test() { + #[derive(Serialize)] + enum B { + A, + B, + } + + #[derive(Serialize)] + struct A { + a: B, + b: HashMap, + } + + let v = A { + a: B::A, + b: [("a".into(), "a".into())].into_iter().collect(), + }; + + 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); + } + + #[test] + fn test2() { + #[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); + } } 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..2a229ac52 100644 --- a/tests/465_no_comment_char_value.rs +++ b/tests/465_no_comment_char_value.rs @@ -4,10 +4,10 @@ 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)), From f4609580c87491ce599713d07d646b9e1875edaf Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Mon, 6 Jan 2025 06:58:50 +0100 Subject: [PATCH 02/13] fmt --- src/ser/value.rs | 2 +- tests/465_no_comment_char_value.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ser/value.rs b/src/ser/value.rs index 05c43015b..a7ba6bb5a 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -33,7 +33,7 @@ impl Serialize for Value { // 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 { diff --git a/tests/465_no_comment_char_value.rs b/tests/465_no_comment_char_value.rs index 2a229ac52..d14bf7458 100644 --- a/tests/465_no_comment_char_value.rs +++ b/tests/465_no_comment_char_value.rs @@ -8,6 +8,8 @@ fn value_deserialises_r_name() { ); assert_eq!( ron::from_str("A(\"/\")"), - Ok(ron::Value::List(vec![ron::Value::String(String::from("/"))])) + Ok(ron::Value::List(vec![ron::Value::String(String::from( + "/" + ))])) ); } From 4db98cd3b303d8421964be6bdc94b96f6bcf6dde Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Mon, 6 Jan 2025 07:01:53 +0100 Subject: [PATCH 03/13] add NamedUnit --- src/value/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 2478d2dd2..65d7c4629 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -21,17 +21,18 @@ pub use raw::RawValue; #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum Value { + Unit, Bool(bool), Char(char), - Map(Map), - Struct(Option, Map), Number(Number), - Option(Option>), String(String), Bytes(Vec), + Option(Option>), List(Vec), + Map(Map), Tuple(Option, Vec), - Unit, + NamedUnit(Cow<'static, str>), + Struct(Option>, Map>), } impl From for Value { From 826bf755d4ad05c3f981cf13950d1c205ade6791 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Mon, 6 Jan 2025 07:15:38 +0100 Subject: [PATCH 04/13] Update mod.rs --- src/value/mod.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 65d7c4629..c5ac2def8 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -30,9 +30,17 @@ pub enum Value { Option(Option>), List(Vec), Map(Map), - Tuple(Option, Vec), - NamedUnit(Cow<'static, str>), + Tuple(Vec), + + UnitStructOrEnumVariant(Cow<'static, str>), + UnitEnumVariant(Cow<'static, str>), + UnitStruct(Cow<'static, str>), + + StructOrEnumVariant(Option>, Map>), Struct(Option>, Map>), + EnumVariant(Cow<'static, str>, Map>), + + EnumTuple(Cow<'static, str>, Vec), } impl From for Value { From 0891537260b4986ea761e75944d60d5ac6641a11 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:45:09 +0100 Subject: [PATCH 05/13] pass compilation + make a test which don't pass --- src/de/value.rs | 2 +- src/lib.rs | 1 + src/ser/value.rs | 76 +++++++++++++++++++++++++++--------------------- src/value/map.rs | 22 +++++++------- src/value/mod.rs | 27 +++++++++++++++++ 5 files changed, 83 insertions(+), 45 deletions(-) diff --git a/src/de/value.rs b/src/de/value.rs index a9835e5c7..faf687136 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -221,7 +221,7 @@ impl<'de> Visitor<'de> for ValueVisitor { 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() { 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/ser/value.rs b/src/ser/value.rs index a7ba6bb5a..8b6119ccc 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -7,16 +7,16 @@ 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::List(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::Struct(name, map) => { // serializer.serialize_struct(name, len) @@ -37,40 +37,50 @@ impl Serialize for Value { // https://github.com/serde-rs/json/blob/master/src/value/ser.rs match name { - Some(name) => { - let mut state = serializer.serialize_struct("", map.len())?; + Some(name) => match name { + std::borrow::Cow::Borrowed(a) => { + let mut state = serializer.serialize_struct(a, map.len())?; - for (k, v) in map { - state.serialize_field(&k, &v)?; - } + 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() - } + state.end() + } + std::borrow::Cow::Owned(_) => todo!(), + }, None => { todo!() + // let mut state = serializer.serialize_struct("", map.len())?; + + // for (k, v) in map { + // state.serialize_field(&k, &v)?; + // } + + // state.end() } } } - Value::Tuple(name, vec) => match name { - Some(name) => { - let mut state = serializer.serialize_tuple_struct("", vec.len())?; + Value::Tuple(vec) => { + let mut state = serializer.serialize_tuple(vec.len())?; - for v in vec { - state.serialize_field(&v)?; - } - - state.end() + for v in vec { + state.serialize_element(&v)?; } - None => { - let mut state = serializer.serialize_tuple(vec.len())?; - - for v in vec { - state.serialize_element(&v)?; - } - state.end() - } - }, + state.end() + } + Value::UnitStructOrEnumVariant(cow) => todo!(), + Value::UnitEnumVariant(cow) => todo!(), + Value::UnitStruct(cow) => todo!(), + Value::StructOrEnumVariant(cow, map) => todo!(), + Value::EnumVariant(cow, map) => todo!(), + Value::EnumTuple(cow, vec) => todo!(), } } } diff --git a/src/value/map.rs b/src/value/map.rs index 937f35273..53d7be01b 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -17,20 +17,20 @@ use super::Value; /// to preserve the order of the parsed map. #[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; #[cfg(feature = "indexmap")] type MapInner = indexmap::IndexMap; -impl Default for Map { +impl Default for Map { fn default() -> Self { Self(Default::default()) } } -impl Map { +impl Map { /// Creates a new, empty [`Map`]. #[must_use] pub fn new() -> Self { @@ -122,7 +122,7 @@ impl Map { } } -impl Index<&Key> for Map { +impl Index<&Key> for Map { type Output = Value; #[allow(clippy::expect_used)] @@ -131,14 +131,14 @@ impl Index<&Key> for Map { } } -impl IndexMut<&Key> for Map { +impl IndexMut<&Key> for Map { #[allow(clippy::expect_used)] fn index_mut(&mut self, index: &Key) -> &mut Self::Output { self.get_mut(index).expect("no entry found for key") } } -impl IntoIterator for Map { +impl IntoIterator for Map { type Item = (Key, Value); type IntoIter = as IntoIterator>::IntoIter; @@ -148,7 +148,7 @@ impl IntoIterator for Map { } } -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() @@ -158,22 +158,22 @@ 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 { +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 { +impl PartialOrd for Map { fn partial_cmp(&self, other: &Map) -> Option { Some(self.cmp(other)) } } -impl Ord for Map { +impl Ord for Map { fn cmp(&self, other: &Map) -> Ordering { self.iter().cmp(other.iter()) } diff --git a/src/value/mod.rs b/src/value/mod.rs index c5ac2def8..17c183ba0 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -202,6 +202,14 @@ impl<'de> Deserializer<'de> for Value { } } Value::Unit => visitor.visit_unit(), + Value::Tuple(vec) => todo!(), + Value::UnitStructOrEnumVariant(cow) => todo!(), + Value::UnitEnumVariant(cow) => todo!(), + Value::UnitStruct(cow) => todo!(), + Value::StructOrEnumVariant(cow, map) => todo!(), + Value::Struct(cow, map) => todo!(), + Value::EnumVariant(cow, map) => todo!(), + Value::EnumTuple(cow, vec) => todo!(), } } } @@ -513,6 +521,24 @@ mod tests { ); } + #[test] + fn empty_struct() { + #[derive(Debug, Deserialize, PartialEq)] + struct A {} + assert_same::("A()"); + } + + #[test] + fn simple_enum() { + #[derive(Debug, Deserialize, PartialEq)] + enum A { + A, + } + + assert_same::("A"); + } + + #[ignore = ""] #[test] fn test() { #[derive(Serialize)] @@ -547,6 +573,7 @@ mod tests { assert_eq!(ron_str, ron_str2); } + #[ignore = ""] #[test] fn test2() { #[derive(Serialize)] From 43415626d3fa5f965e6b8a3d69f772ab70b911bc Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Thu, 24 Jul 2025 20:59:03 +0200 Subject: [PATCH 06/13] fix build errors --- src/de/value.rs | 2 +- src/value/mod.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/de/value.rs b/src/de/value.rs index faf687136..66557b924 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -306,7 +306,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)), diff --git a/src/value/mod.rs b/src/value/mod.rs index 17c183ba0..0b60534a7 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -541,6 +541,8 @@ mod tests { #[ignore = ""] #[test] fn test() { + use std::collections::HashMap; + use std::println; #[derive(Serialize)] enum B { A, @@ -576,6 +578,9 @@ mod tests { #[ignore = ""] #[test] fn test2() { + use std::collections::HashMap; + use std::println; + #[derive(Serialize)] enum B { A(Option, i32), From 6ea682ecfdc035198a82812351db5a2fb98f8915 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Thu, 24 Jul 2025 23:35:20 +0200 Subject: [PATCH 07/13] rework Value type --- src/de/mod.rs | 3 +++ src/de/value.rs | 31 +++++++++++++++++++++++++++++++ src/ser/value.rs | 39 +++++++++++---------------------------- src/value/mod.rs | 36 +++++++++++++++++++----------------- 4 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index 1dd019134..d3d318bdf 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -200,6 +200,9 @@ impl<'de> Deserializer<'de> { // serde's Content type needs the ident for unit variants visitor.visit_str(ident) } + (StructType::Unit, Some(ident)) => { + visitor.visit_str(ident) + } (StructType::Unit, _) => visitor.visit_unit(), (_, Some(ident)) if is_serde_content => { // serde's Content type uses a singleton map encoding for enums diff --git a/src/de/value.rs b/src/de/value.rs index 66557b924..8aabd260c 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -234,6 +234,37 @@ 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() { + return Ok(Value::NamedUnit { + name: variant.into(), + }); + } else { + return Ok(Value::Unit); + }; + + // let value = if let Ok(v) = variant_access.unit_variant() { + // Value::Unit + // } else if let Ok(v) = variant_access.newtype_variant_seed(ValueVisitor) { + // v + // } else if let Ok(v) = variant_access.tuple_variant(0, ValueVisitor) { + // v + // } else if let Ok(v) = variant_access.struct_variant(&[], ValueVisitor) { + // v + // } else { + // // fallback: treat as unit + // Value::Unit + // }; + } } #[cfg(test)] diff --git a/src/ser/value.rs b/src/ser/value.rs index 8b6119ccc..754afa562 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -18,7 +18,7 @@ impl Serialize for Value { Value::Bytes(b) => serializer.serialize_bytes(b), Value::List(s) => Serialize::serialize(s, serializer), Value::Unit => serializer.serialize_unit(), - Value::Struct(name, map) => { + Value::NamedStruct(name, map) => { // serializer.serialize_struct(name, len) // serializer.serialize_struct_variant(name, variant_index, variant, len) @@ -37,33 +37,21 @@ impl Serialize for Value { // https://github.com/serde-rs/json/blob/master/src/value/ser.rs match name { - Some(name) => match name { - std::borrow::Cow::Borrowed(a) => { - let mut state = serializer.serialize_struct(a, map.len())?; + 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!(), + 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!(), - }, - None => { - todo!() - // let mut state = serializer.serialize_struct("", map.len())?; - - // for (k, v) in map { - // state.serialize_field(&k, &v)?; - // } - // state.end() + state.end() } + std::borrow::Cow::Owned(_) => todo!(), } } Value::Tuple(vec) => { @@ -75,12 +63,7 @@ impl Serialize for Value { state.end() } - Value::UnitStructOrEnumVariant(cow) => todo!(), - Value::UnitEnumVariant(cow) => todo!(), - Value::UnitStruct(cow) => todo!(), - Value::StructOrEnumVariant(cow, map) => todo!(), - Value::EnumVariant(cow, map) => todo!(), - Value::EnumTuple(cow, vec) => todo!(), + _ => todo!(), } } } diff --git a/src/value/mod.rs b/src/value/mod.rs index 0b60534a7..1f29c556b 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -21,6 +21,7 @@ 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 typee Unit, Bool(bool), Char(char), @@ -32,15 +33,21 @@ pub enum Value { Map(Map), Tuple(Vec), - UnitStructOrEnumVariant(Cow<'static, str>), - UnitEnumVariant(Cow<'static, str>), - UnitStruct(Cow<'static, str>), - - StructOrEnumVariant(Option>, Map>), - Struct(Option>, Map>), - EnumVariant(Cow<'static, str>, Map>), - - EnumTuple(Cow<'static, str>, 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 + NamedStruct(Cow<'static, str>, Map>), + /// Enum or struct + NamedTuple(Cow<'static, str>, Vec), } impl From for Value { @@ -202,14 +209,7 @@ impl<'de> Deserializer<'de> for Value { } } Value::Unit => visitor.visit_unit(), - Value::Tuple(vec) => todo!(), - Value::UnitStructOrEnumVariant(cow) => todo!(), - Value::UnitEnumVariant(cow) => todo!(), - Value::UnitStruct(cow) => todo!(), - Value::StructOrEnumVariant(cow, map) => todo!(), - Value::Struct(cow, map) => todo!(), - Value::EnumVariant(cow, map) => todo!(), - Value::EnumTuple(cow, vec) => todo!(), + _ => todo!(), } } } @@ -278,6 +278,7 @@ impl<'a, 'de> MapAccess<'de> for MapAccessor<'a> { mod tests { use alloc::{collections::BTreeMap, vec}; use core::fmt::Debug; + use std::dbg; use serde::{Deserialize, Serialize}; @@ -291,6 +292,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); From 2a1910d2f1eebcb6b5108eefe5d2f3387d2eabe8 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 25 Jul 2025 01:43:58 +0200 Subject: [PATCH 08/13] deser simple enum --- src/de/mod.rs | 57 ++++++++++++++++++++++++++++++++++++++++-------- src/de/value.rs | 21 ++++++++++++++++-- src/error.rs | 9 ++++++++ src/parse.rs | 2 +- src/value/mod.rs | 1 + 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index d3d318bdf..f96f8bed8 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,7 @@ 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>, { @@ -201,7 +201,9 @@ impl<'de> Deserializer<'de> { visitor.visit_str(ident) } (StructType::Unit, Some(ident)) => { - visitor.visit_str(ident) + self.parser.cursor = cursor; + let enum_access = Enum::new(self, EnumKind::Unit); + visitor.visit_enum(enum_access) } (StructType::Unit, _) => visitor.visit_unit(), (_, Some(ident)) if is_serde_content => { @@ -344,15 +346,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), @@ -747,7 +751,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, @@ -907,13 +911,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 } } } @@ -937,13 +950,25 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { type Error = Error; fn unit_variant(self) -> Result<()> { - Ok(()) + 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()?; @@ -981,6 +1006,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) @@ -990,6 +1022,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 8aabd260c..991335467 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -240,13 +240,13 @@ impl<'de> Visitor<'de> for ValueVisitor { A: serde::de::EnumAccess<'de>, { // Get the variant name and the VariantAccess - let (variant, variant_access) = data.variant::()?; + 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() { return Ok(Value::NamedUnit { - name: variant.into(), + name: variant.0.into(), }); } else { return Ok(Value::Unit); @@ -267,6 +267,23 @@ impl<'de> Visitor<'de> for ValueVisitor { } } +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)] mod tests { use alloc::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/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/value/mod.rs b/src/value/mod.rs index 1f29c556b..0dfb480db 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -209,6 +209,7 @@ impl<'de> Deserializer<'de> for Value { } } Value::Unit => visitor.visit_unit(), + // Value::NamedUnit { name } => visitor.visit_enum(data), _ => todo!(), } } From 95816b9fc495c5b471d3889c799ebf160637006d Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 25 Jul 2025 03:19:18 +0200 Subject: [PATCH 09/13] impl more of deser for Value --- src/value/mod.rs | 126 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 3 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 0dfb480db..9bcab5efe 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, }; @@ -209,8 +213,38 @@ impl<'de> Deserializer<'de> for Value { } } Value::Unit => visitor.visit_unit(), - // Value::NamedUnit { name } => visitor.visit_enum(data), - _ => todo!(), + 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::NamedStruct(name, map) => visitor.visit_enum(EnumAccessor { + variant: name.to_string(), + value: Value::NamedStruct(name, map), + }), + Value::NamedTuple(name, values) => visitor.visit_enum(EnumAccessor { + variant: name.to_string(), + value: Value::NamedTuple(name, values), + }), } } } @@ -275,6 +309,92 @@ 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::NamedStruct(_, 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}; From 63c11a6dc23b241019c09fef7383a091cbb1fb9b Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 25 Jul 2025 03:30:07 +0200 Subject: [PATCH 10/13] add todo --- src/de/value.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/de/value.rs b/src/de/value.rs index 991335467..d851a465b 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -252,6 +252,8 @@ impl<'de> Visitor<'de> for ValueVisitor { return Ok(Value::Unit); }; + // todo: complete this function + // let value = if let Ok(v) = variant_access.unit_variant() { // Value::Unit // } else if let Ok(v) = variant_access.newtype_variant_seed(ValueVisitor) { @@ -274,13 +276,15 @@ impl<'de> Deserialize<'de> for Ident { where D: Deserializer<'de>, { - deserializer.deserialize_identifier(ValueVisitor).and_then(|e| { - if let Value::String(ident) = e { - Ok(Ident(ident)) - } else { - unreachable!() - } - }) + deserializer + .deserialize_identifier(ValueVisitor) + .and_then(|e| { + if let Value::String(ident) = e { + Ok(Ident(ident)) + } else { + unreachable!() + } + }) } } From 5811ebae42c90cc668f37e8687e10132a5bd347e Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:54:09 +0200 Subject: [PATCH 11/13] add more test --- src/value/mod.rs | 90 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 9bcab5efe..fe393d61a 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -25,7 +25,7 @@ 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 typee + /// Can represent a struct with no field, or the Unit type Unit, Bool(bool), Char(char), @@ -34,6 +34,7 @@ pub enum Value { Bytes(Vec), Option(Option>), List(Vec), + /// Can be a struct Map(Map), Tuple(Vec), @@ -383,8 +384,10 @@ impl<'a, 'de> VariantAccess<'de> for VariantAccessor { V: Visitor<'de>, { if let Value::NamedStruct(_, mut map) = self.value { - let mut items: Vec<(Value, Value)> = - map.into_iter().map(|e| (Value::String(e.0.to_string()), e.1)).collect(); + 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, @@ -553,7 +556,7 @@ mod tests { } #[test] - fn seq() { + fn list() { assert_same::>("[1.0, 2.0, 3.0, 4.0]"); assert_eq!( @@ -645,14 +648,14 @@ mod tests { } #[test] - fn empty_struct() { + fn unit_struct() { #[derive(Debug, Deserialize, PartialEq)] - struct A {} + struct A; assert_same::("A()"); } #[test] - fn simple_enum() { + fn unit_enum() { #[derive(Debug, Deserialize, PartialEq)] enum A { A, @@ -661,26 +664,82 @@ mod tests { assert_same::("A"); } + #[test] + fn new_type_struct() { + #[derive(Debug, Deserialize, PartialEq)] + struct A(i32); + + assert_same::("A(1)"); + } + + #[test] + 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] + 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] + 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 B { + enum Enum { A, B, } #[derive(Serialize)] - struct A { - a: B, - b: HashMap, + struct Struct { + e: Enum, + h: HashMap, } - let v = A { - a: B::A, - b: [("a".into(), "a".into())].into_iter().collect(), + let v = Struct { + e: Enum::A, + h: [("hello".into(), "world".into())].into_iter().collect(), }; let ron_str = crate::to_string(&v).unwrap(); @@ -689,7 +748,8 @@ mod tests { let value = crate::from_str::(&ron_str).unwrap(); - println!("{:?}", value); + dbg!(&value); + // println!("{:?}", value); let ron_str2 = crate::to_string(&value).unwrap(); From c04b595a55f395bb3b9477068abcffaab22d6c92 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:52:24 +0200 Subject: [PATCH 12/13] rename namedstruct to namedmap --- src/de/mod.rs | 28 ++++++++++++++++------------ src/de/value.rs | 1 + src/ser/value.rs | 2 +- src/value/mod.rs | 35 ++++++++++++++++++++++++++++++----- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index f96f8bed8..c4b5befca 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -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>, cursor: ParserCursor) -> Result + fn handle_any_struct( + &mut self, + visitor: V, + ident: Option<&str>, + cursor: ParserCursor, + ) -> Result where V: Visitor<'de>, { @@ -185,17 +190,16 @@ 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) diff --git a/src/de/value.rs b/src/de/value.rs index d851a465b..8dcd87458 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -269,6 +269,7 @@ impl<'de> Visitor<'de> for ValueVisitor { } } +// todo: use id::Deserializer ? struct Ident(String); impl<'de> Deserialize<'de> for Ident { diff --git a/src/ser/value.rs b/src/ser/value.rs index 754afa562..eb7a80a7c 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -18,7 +18,7 @@ impl Serialize for Value { Value::Bytes(b) => serializer.serialize_bytes(b), Value::List(s) => Serialize::serialize(s, serializer), Value::Unit => serializer.serialize_unit(), - Value::NamedStruct(name, map) => { + Value::NamedMap(name, map) => { // serializer.serialize_struct(name, len) // serializer.serialize_struct_variant(name, variant_index, variant, len) diff --git a/src/value/mod.rs b/src/value/mod.rs index fe393d61a..2c0fc8dfc 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -50,7 +50,7 @@ pub enum Value { inner: Box, }, /// Enum or struct - NamedStruct(Cow<'static, str>, Map>), + NamedMap(Cow<'static, str>, Map>), /// Enum or struct NamedTuple(Cow<'static, str>, Vec), } @@ -238,9 +238,9 @@ impl<'de> Deserializer<'de> for Value { variant: name.to_string(), value: Value::NamedNewtype { name, inner }, }), - Value::NamedStruct(name, map) => visitor.visit_enum(EnumAccessor { + Value::NamedMap(name, map) => visitor.visit_enum(EnumAccessor { variant: name.to_string(), - value: Value::NamedStruct(name, map), + value: Value::NamedMap(name, map), }), Value::NamedTuple(name, values) => visitor.visit_enum(EnumAccessor { variant: name.to_string(), @@ -383,7 +383,7 @@ impl<'a, 'de> VariantAccess<'de> for VariantAccessor { where V: Visitor<'de>, { - if let Value::NamedStruct(_, mut map) = self.value { + 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)) @@ -648,9 +648,16 @@ mod tests { } #[test] - fn unit_struct() { + 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()"); } @@ -673,6 +680,7 @@ mod tests { } #[test] + // panic fn new_type_enum() { #[derive(Debug, Deserialize, PartialEq)] enum A { @@ -690,6 +698,7 @@ mod tests { } #[test] + // panic fn tuple_enum() { #[derive(Debug, Deserialize, PartialEq)] enum A { @@ -711,6 +720,7 @@ mod tests { } #[test] + // panic fn r#enum() { #[derive(Debug, Deserialize, PartialEq)] enum A { @@ -793,4 +803,19 @@ mod tests { 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); + } } From 1b58293b55e4ead83ad54121a894e18a129450f7 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 25 Jul 2025 21:36:06 +0200 Subject: [PATCH 13/13] don't compile, need a refractor in EnumAccess --- src/de/mod.rs | 30 +++++++++++++++++++++++---- src/de/value.rs | 54 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index c4b5befca..76d9b24bb 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -198,7 +198,7 @@ impl<'de> Deserializer<'de> { 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 @@ -209,7 +209,7 @@ impl<'de> Deserializer<'de> { let enum_access = Enum::new(self, EnumKind::Unit); visitor.visit_enum(enum_access) } - (StructType::Unit, _) => visitor.visit_unit(), + (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 { @@ -217,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('('); @@ -231,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) @@ -954,6 +975,7 @@ impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { type Error = Error; fn unit_variant(self) -> Result<()> { + // todo: consume () if exist ? match self.kind { EnumKind::Unknown | EnumKind::Unit => Ok(()), EnumKind::NewType => Err(Error::ExpectedNamedNewType), diff --git a/src/de/value.rs b/src/de/value.rs index 8dcd87458..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}, @@ -241,31 +242,48 @@ impl<'de> Visitor<'de> for ValueVisitor { { // 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() { - return Ok(Value::NamedUnit { + 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 { - return Ok(Value::Unit); + // fallback: treat as unit + Value::Unit }; - // todo: complete this function - - // let value = if let Ok(v) = variant_access.unit_variant() { - // Value::Unit - // } else if let Ok(v) = variant_access.newtype_variant_seed(ValueVisitor) { - // v - // } else if let Ok(v) = variant_access.tuple_variant(0, ValueVisitor) { - // v - // } else if let Ok(v) = variant_access.struct_variant(&[], ValueVisitor) { - // v - // } else { - // // fallback: treat as unit - // Value::Unit - // }; + Ok(value) } }