Skip to content

Commit fca64c6

Browse files
authored
Merge pull request #234 from jcaesar/maporder
Preserve order of items in maps
2 parents 7c510c8 + ecb5c35 commit fca64c6

4 files changed

Lines changed: 109 additions & 38 deletions

File tree

Cargo.lock

Lines changed: 84 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,18 @@ serde-hjson = "0.9.1"
4646
serde-protobuf = "0.8.1"
4747
serde_cbor = "0.11.2"
4848
serde_json = "1.0.81"
49-
serde_yaml = "0.8.24"
49+
serde_yaml = "0.9.16"
5050
structopt = "0.3.26"
51-
toml = "0.5.9"
5251
yaml-rust = "0.4.5"
5352

5453
[dependencies.avro-rs]
5554
version = "0.6.5"
5655
features = ["snappy"]
5756

57+
[dependencies.toml]
58+
version = "0.6.0"
59+
features = ["preserve_order"]
60+
5861
[profile.release]
5962
lto = true
6063
codegen-units = 1

src/value/mod.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use crate::error;
33
use ordered_float;
44
use serde;
55
use serde_json;
6-
use std::collections;
76
use std::fmt;
87
use std::io;
98

@@ -17,7 +16,7 @@ pub mod raw;
1716
pub mod toml;
1817
pub mod yaml;
1918

20-
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
19+
#[derive(Debug)]
2120
pub enum Value {
2221
Unit,
2322
Bool(bool),
@@ -40,8 +39,10 @@ pub enum Value {
4039
Bytes(Vec<u8>),
4140

4241
Sequence(Vec<Value>),
43-
// TODO: Use a container that preserves insertion order
44-
Map(collections::BTreeMap<Value, Value>),
42+
43+
// A sequence of pairs is appropriate for representing an object/a map:
44+
// there is no need to deduplicate keys, and it is nice to preserve order.
45+
Map(Vec<(Value, Value)>),
4546
}
4647

4748
pub trait Source {
@@ -159,7 +160,14 @@ impl serde::ser::Serialize for Value {
159160
Self::Bytes(ref v) => v.serialize(s),
160161

161162
Self::Sequence(ref v) => v.serialize(s),
162-
Self::Map(ref v) => v.serialize(s),
163+
Self::Map(ref v) => {
164+
use serde::ser::SerializeMap;
165+
let mut s = s.serialize_map(Some(v.len()))?;
166+
for (key, value) in v {
167+
SerializeMap::serialize_entry(&mut s, key, value)?;
168+
}
169+
SerializeMap::end(s)
170+
}
163171
}
164172
}
165173
}
@@ -353,10 +361,10 @@ impl<'de> serde::de::Visitor<'de> for ValueVisitor {
353361
where
354362
V: serde::de::MapAccess<'de>,
355363
{
356-
let mut values = collections::BTreeMap::new();
364+
let mut values = Vec::new();
357365

358-
while let Some((key, value)) = v.next_entry()? {
359-
values.insert(key, value);
366+
while let Some(entry) = v.next_entry()? {
367+
values.push(entry);
360368
}
361369

362370
Ok(Value::Map(values))

src/value/toml.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ impl value::Source for Source {
3535
fn read(&mut self) -> error::Result<Option<value::Value>> {
3636
match self.0.take() {
3737
Some(v) => {
38-
let mut de = toml::de::Deserializer::new(v.as_str());
39-
match serde::Deserialize::deserialize(&mut de) {
38+
let de = toml::de::Deserializer::new(v.as_str());
39+
match serde::Deserialize::deserialize(de) {
4040
Ok(v) => Ok(Some(v)),
4141
Err(e) => Err(error::Error::from(e)),
4242
}
@@ -54,8 +54,8 @@ where
5454
fn write(&mut self, value: value::Value) -> error::Result<()> {
5555
let mut string = String::new();
5656
{
57-
let mut ser = toml::ser::Serializer::new(&mut string);
58-
serde::Serialize::serialize(&value, &mut ser)?;
57+
let ser = toml::ser::Serializer::new(&mut string);
58+
serde::Serialize::serialize(&value, ser)?;
5959
}
6060

6161
self.0.write_all(string.as_bytes())?;

0 commit comments

Comments
 (0)