Skip to content

Commit bee1974

Browse files
committed
Fix ron-rs#277 and ron-rs#405 with Value::Map IntoIter and extraneous item check for Value::Seq
1 parent fc6d4b8 commit bee1974

File tree

3 files changed

+102
-21
lines changed

3 files changed

+102
-21
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## Unreleased
88

9+
- Fix issues [#277](https://github.com/ron-rs/ron/issues/277) and [#405](https://github.com/ron-rs/ron/issues/405) with `Value::Map` `IntoIter` and extraneous item check for `Value::Seq` ([#406](https://github.com/ron-rs/ron/pull/406))
10+
911
## [0.8.0] - 2022-08-17
1012

1113
- Bump dependencies: `bitflags` to 1.3, `indexmap` to 1.9 ([#399](https://github.com/ron-rs/ron/pull/399))

src/value.rs

+68-20
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ impl FromIterator<(Value, Value)> for Map {
8383
}
8484
}
8585

86+
impl IntoIterator for Map {
87+
type Item = (Value, Value);
88+
89+
type IntoIter = <MapInner as IntoIterator>::IntoIter;
90+
91+
fn into_iter(self) -> Self::IntoIter {
92+
self.0.into_iter()
93+
}
94+
}
95+
8696
/// Note: equality is only given if both values and order of values match
8797
impl Eq for Map {}
8898

@@ -353,18 +363,45 @@ impl<'de> Deserializer<'de> for Value {
353363
match self {
354364
Value::Bool(b) => visitor.visit_bool(b),
355365
Value::Char(c) => visitor.visit_char(c),
356-
Value::Map(m) => visitor.visit_map(MapAccessor {
357-
keys: m.keys().cloned().rev().collect(),
358-
values: m.values().cloned().rev().collect(),
359-
}),
366+
Value::Map(m) => {
367+
let old_len = m.len();
368+
369+
let mut items: Vec<(Value, Value)> = m.into_iter().collect();
370+
items.reverse();
371+
372+
let value = visitor.visit_map(MapAccessor {
373+
items: &mut items,
374+
value: None,
375+
})?;
376+
377+
if items.is_empty() {
378+
Ok(value)
379+
} else {
380+
Err(Error::ExpectedDifferentLength {
381+
expected: format!("a map of length {}", old_len - items.len()),
382+
found: old_len,
383+
})
384+
}
385+
}
360386
Value::Number(Number::Float(ref f)) => visitor.visit_f64(f.get()),
361387
Value::Number(Number::Integer(i)) => visitor.visit_i64(i),
362388
Value::Option(Some(o)) => visitor.visit_some(*o),
363389
Value::Option(None) => visitor.visit_none(),
364390
Value::String(s) => visitor.visit_string(s),
365391
Value::Seq(mut seq) => {
392+
let old_len = seq.len();
393+
366394
seq.reverse();
367-
visitor.visit_seq(Seq { seq })
395+
let value = visitor.visit_seq(Seq { seq: &mut seq })?;
396+
397+
if seq.is_empty() {
398+
Ok(value)
399+
} else {
400+
Err(Error::ExpectedDifferentLength {
401+
expected: format!("a sequence of length {}", old_len - seq.len()),
402+
found: old_len,
403+
})
404+
}
368405
}
369406
Value::Unit => visitor.visit_unit(),
370407
}
@@ -433,41 +470,48 @@ impl<'de> Deserializer<'de> for Value {
433470
}
434471
}
435472

436-
struct MapAccessor {
437-
keys: Vec<Value>,
438-
values: Vec<Value>,
473+
struct MapAccessor<'a> {
474+
items: &'a mut Vec<(Value, Value)>,
475+
value: Option<Value>,
439476
}
440477

441-
impl<'de> MapAccess<'de> for MapAccessor {
478+
impl<'a, 'de> MapAccess<'de> for MapAccessor<'a> {
442479
type Error = Error;
443480

444481
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
445482
where
446483
K: DeserializeSeed<'de>,
447484
{
448485
// The `Vec` is reversed, so we can pop to get the originally first element
449-
self.keys
450-
.pop()
451-
.map_or(Ok(None), |v| seed.deserialize(v).map(Some))
486+
match self.items.pop() {
487+
Some((key, value)) => {
488+
self.value = Some(value);
489+
seed.deserialize(key).map(Some)
490+
}
491+
None => Ok(None),
492+
}
452493
}
453494

454495
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
455496
where
456497
V: DeserializeSeed<'de>,
457498
{
458-
// The `Vec` is reversed, so we can pop to get the originally first element
459-
self.values
460-
.pop()
461-
.map(|v| seed.deserialize(v))
462-
.expect("Contract violation")
499+
match self.value.take() {
500+
Some(value) => seed.deserialize(value),
501+
None => panic!("Contract violation: value before key"),
502+
}
503+
}
504+
505+
fn size_hint(&self) -> Option<usize> {
506+
Some(self.items.len())
463507
}
464508
}
465509

466-
struct Seq {
467-
seq: Vec<Value>,
510+
struct Seq<'a> {
511+
seq: &'a mut Vec<Value>,
468512
}
469513

470-
impl<'de> SeqAccess<'de> for Seq {
514+
impl<'a, 'de> SeqAccess<'de> for Seq<'a> {
471515
type Error = Error;
472516

473517
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
@@ -479,6 +523,10 @@ impl<'de> SeqAccess<'de> for Seq {
479523
.pop()
480524
.map_or(Ok(None), |v| seed.deserialize(v).map(Some))
481525
}
526+
527+
fn size_hint(&self) -> Option<usize> {
528+
Some(self.seq.len())
529+
}
482530
}
483531

484532
#[cfg(test)]

tests/value.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::f64;
22

3-
use ron::value::{Map, Number, Value};
3+
use ron::{
4+
error::Error,
5+
value::{Map, Number, Value},
6+
};
47
use serde::Serialize;
58

69
#[test]
@@ -68,6 +71,34 @@ fn seq() {
6871
Value::Number(Number::new(2f64)),
6972
];
7073
assert_eq!("[1, 2.0]".parse(), Ok(Value::Seq(seq)));
74+
75+
let err = Value::Seq(vec![Value::Number(Number::new(1))])
76+
.into_rust::<[i32; 2]>()
77+
.unwrap_err();
78+
79+
assert_eq!(
80+
err,
81+
Error::ExpectedDifferentLength {
82+
expected: String::from("an array of length 2"),
83+
found: 1,
84+
}
85+
);
86+
87+
let err = Value::Seq(vec![
88+
Value::Number(Number::new(1)),
89+
Value::Number(Number::new(2)),
90+
Value::Number(Number::new(3)),
91+
])
92+
.into_rust::<[i32; 2]>()
93+
.unwrap_err();
94+
95+
assert_eq!(
96+
err,
97+
Error::ExpectedDifferentLength {
98+
expected: String::from("a sequence of length 2"),
99+
found: 3,
100+
}
101+
);
71102
}
72103

73104
#[test]

0 commit comments

Comments
 (0)