Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to make str -> ron::Value lossless #553

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/de/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
vec.push(x);
}

Ok(Value::Seq(vec))
Ok(Value::List(vec))
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
Expand Down Expand Up @@ -263,7 +263,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())),
Expand All @@ -275,7 +275,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)),
Expand All @@ -301,7 +301,7 @@ mod tests {
fn test_floats() {
assert_eq!(
eval("(inf, -inf, NaN)"),
Value::Seq(vec![
Value::List(vec![
Value::Number(Number::new(std::f32::INFINITY)),
Value::Number(Number::new(std::f32::NEG_INFINITY)),
Value::Number(Number::new(std::f32::NAN)),
Expand All @@ -328,7 +328,7 @@ mod tests {
),
])"
),
Value::Option(Some(Box::new(Value::Seq(vec![
Value::Option(Some(Box::new(Value::List(vec![
Value::Map(
vec![
(
Expand Down
57 changes: 55 additions & 2 deletions src/ser/value.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use serde::ser::{Serialize, Serializer};
use serde::ser::{Serialize, SerializeStruct, SerializeTuple, SerializeTupleStruct, Serializer};

use crate::value::Value;

Expand All @@ -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()
}
},
}
}
}
66 changes: 36 additions & 30 deletions src/value/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Key: Ord>(pub(crate) MapInner<Key>);

#[cfg(not(feature = "indexmap"))]
type MapInner = std::collections::BTreeMap<Value, Value>;
type MapInner<Key> = std::collections::BTreeMap<Key, Value>;
#[cfg(feature = "indexmap")]
type MapInner = indexmap::IndexMap<Value, Value>;
type MapInner<Key> = indexmap::IndexMap<Key, Value>;

impl Map {
impl<Key: Ord> Default for Map<Key> {
fn default() -> Self {
Self(Default::default())
}
}

impl<Key: Ord> Map<Key> {
/// Creates a new, empty [`Map`].
#[must_use]
pub fn new() -> Self {
Expand All @@ -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>, value: impl Into<Value>) -> Option<Value> {
pub fn insert(&mut self, key: impl Into<Key>, value: impl Into<Value>) -> Option<Value> {
self.0.insert(key.into(), value.into())
}

/// Removes an element by its `key`.
pub fn remove(&mut self, key: &Value) -> Option<Value> {
pub fn remove(&mut self, key: &Key) -> Option<Value> {
#[cfg(feature = "indexmap")]
{
self.0.shift_remove(key)
Expand All @@ -74,19 +80,19 @@ impl Map {

/// Iterate all key-value pairs.
#[must_use]
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (&Value, &Value)> {
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (&Key, &Value)> {
self.0.iter()
}

/// Iterate all key-value pairs mutably.
#[must_use]
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (&Value, &mut Value)> {
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (&Key, &mut Value)> {
self.0.iter_mut()
}

/// Iterate all keys.
#[must_use]
pub fn keys(&self) -> impl DoubleEndedIterator<Item = &Value> {
pub fn keys(&self) -> impl DoubleEndedIterator<Item = &Key> {
self.0.keys()
}

Expand All @@ -110,39 +116,39 @@ impl Map {
/// The elements are visited in iteration order.
pub fn retain<F>(&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<Key: Ord> Index<&Key> for Map<Key> {
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<Key: Ord> IndexMut<&Key> for Map<Key> {
#[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<Key: Ord> IntoIterator for Map<Key> {
type Item = (Key, Value);

type IntoIter = <MapInner as IntoIterator>::IntoIter;
type IntoIter = <MapInner<Key> as IntoIterator>::IntoIter;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

impl<K: Into<Value>, V: Into<Value>> FromIterator<(K, V)> for Map {
impl<Key: Ord, K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Map<Key> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
Map(iter
.into_iter()
Expand All @@ -152,28 +158,28 @@ impl<K: Into<Value>, V: Into<Value>> 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<Key: Ord> PartialEq for Map<Key> {
fn eq(&self, other: &Map<Key>) -> bool {
self.cmp(other).is_eq()
}
}

/// Note: equality is only given if both values and order of values match
impl Eq for Map {}
impl<Key: Ord> Eq for Map<Key> {}

impl PartialOrd for Map {
fn partial_cmp(&self, other: &Map) -> Option<Ordering> {
impl<Key: Ord> PartialOrd for Map<Key> {
fn partial_cmp(&self, other: &Map<Key>) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Map {
fn cmp(&self, other: &Map) -> Ordering {
impl<Key: Ord> Ord for Map<Key> {
fn cmp(&self, other: &Map<Key>) -> Ordering {
self.iter().cmp(other.iter())
}
}

impl Hash for Map {
impl<Key: Ord + Hash> Hash for Map<Key> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.iter().for_each(|x| x.hash(state));
}
Expand Down Expand Up @@ -254,7 +260,7 @@ mod tests {
);
}

fn assert_same_hash(a: &Map, b: &Map) {
fn assert_same_hash(a: &Map<Value>, b: &Map<Value>) {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

Expand Down
Loading