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

Add support to preserve_order in no_std #1101

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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.toml
Expand Up @@ -12,7 +12,8 @@ repository = "https://github.com/serde-rs/json"
rust-version = "1.56"

[dependencies]
indexmap = { version = "2", optional = true }
ahash = { version = "0.8", default-features = false, optional = true }
indexmap = { version = "2", default-features = false, optional = true }
itoa = "1.0"
ryu = "1.0"
serde = { version = "1.0.194", default-features = false }
Expand Down Expand Up @@ -55,7 +56,7 @@ alloc = ["serde/alloc"]
# Make serde_json::Map use a representation which maintains insertion order.
# This allows data to be read into a Value and written back to a JSON string
# while preserving the order of map keys in the input.
preserve_order = ["indexmap", "std"]
preserve_order = ["ahash", "indexmap"]

# Use sufficient precision when parsing fixed precision floats from JSON to
# ensure that they maintain accuracy when round-tripped through JSON. This comes
Expand Down
28 changes: 23 additions & 5 deletions src/map.rs
Expand Up @@ -7,6 +7,8 @@
//! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html

use crate::value::Value;
#[cfg(feature = "preserve_order")]
use ahash::RandomState;
use alloc::string::String;
use core::borrow::Borrow;
use core::fmt::{self, Debug};
Expand All @@ -30,14 +32,17 @@ pub struct Map<K, V> {
#[cfg(not(feature = "preserve_order"))]
type MapImpl<K, V> = BTreeMap<K, V>;
#[cfg(feature = "preserve_order")]
type MapImpl<K, V> = IndexMap<K, V>;
type MapImpl<K, V> = IndexMap<K, V, RandomState>;

impl Map<String, Value> {
/// Makes a new empty Map.
#[inline]
pub fn new() -> Self {
Map {
#[cfg(not(feature = "preserve_order"))]
map: MapImpl::new(),
#[cfg(feature = "preserve_order")]
map: MapImpl::with_hasher(RandomState::new()),
}
}

Expand All @@ -52,7 +57,7 @@ impl Map<String, Value> {
BTreeMap::new()
},
#[cfg(feature = "preserve_order")]
map: IndexMap::with_capacity(capacity),
map: IndexMap::with_capacity_and_hasher(capacity, RandomState::new()),
}
}

Expand Down Expand Up @@ -159,8 +164,10 @@ impl Map<String, Value> {
#[inline]
pub fn append(&mut self, other: &mut Self) {
#[cfg(feature = "preserve_order")]
self.map
.extend(mem::replace(&mut other.map, MapImpl::default()));
self.map.extend(mem::replace(
&mut other.map,
MapImpl::with_hasher(RandomState::new()),
));
#[cfg(not(feature = "preserve_order"))]
self.map.append(&mut other.map);
}
Expand Down Expand Up @@ -252,7 +259,10 @@ impl Default for Map<String, Value> {
#[inline]
fn default() -> Self {
Map {
#[cfg(not(feature = "preserve_order"))]
map: MapImpl::new(),
#[cfg(feature = "preserve_order")]
map: MapImpl::with_hasher(RandomState::new()),
}
}
}
Expand Down Expand Up @@ -400,8 +410,16 @@ impl FromIterator<(String, Value)> for Map<String, Value> {
where
T: IntoIterator<Item = (String, Value)>,
{
Map {
Self {
#[cfg(not(feature = "preserve_order"))]
map: FromIterator::from_iter(iter),
#[cfg(feature = "preserve_order")]
map: {
// TODO: replace with `iter.into_iter().collect();` when RandomState will impl Default
let mut map = MapImpl::with_hasher(RandomState::new());
map.extend(iter);
map
},
}
}
}
Expand Down