Skip to content

Commit f3f556e

Browse files
committed
feat(preserve_order): integrate IndexMap support across Value types and deserializers
1 parent c18bb92 commit f3f556e

File tree

11 files changed

+311
-35
lines changed

11 files changed

+311
-35
lines changed

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ rust-version = "1.88"
1414
[dependencies]
1515
simdutf8 = { version = "0.1.4", features = ["public_imp", "aarch64_neon"] }
1616

17-
value-trait = { version = "0.12" }
17+
value-trait = { version = "0.12.1" }
1818
beef = { version = "0.5", optional = true }
1919
halfbrown = "0.4"
2020
# ahash known key
@@ -25,6 +25,9 @@ ahash = { version = "0.8", optional = true }
2525
serde = { version = "1", features = ["derive"], optional = true }
2626
serde_json = { version = "1", optional = true }
2727

28+
# preserve insertion order
29+
indexmap = { version = "2.0", optional = true }
30+
2831
# perf testing
2932
alloc_counter = { version = "0.0.4", optional = true }
3033
colored = { version = "3.0", optional = true }
@@ -62,6 +65,9 @@ default = ["swar-number-parsing", "serde_impl", "runtime-detection"]
6265

6366
arraybackend = ["halfbrown/arraybackend"]
6467

68+
# preserve insertion order
69+
preserve_order = ["dep:indexmap", "value-trait/indexmap"]
70+
6571
# Forces the `owned::Value` and `borrowed::Value` to deduplicate duplicated keys by letting consecutive keys overwrite previous ones. This comes at a
6672
# performance cost. By default duplicate keys will not be overwritten and feeding json objects with duplicated
6773
# keys to either of the `Value`s will result in undefined behavior.

src/serde/value/borrowed/de.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,32 @@ impl<'de> SeqAccess<'de> for ArrayRef<'de> {
176176
}
177177
}
178178

179+
#[cfg(not(feature = "preserve_order"))]
179180
struct ObjectAccess<'de, const N: usize = 32> {
180181
i: halfbrown::IntoIter<Cow<'de, str>, Value<'de>, N>,
181182
v: Option<Value<'de>>,
182183
}
183184

185+
#[cfg(feature = "preserve_order")]
186+
struct ObjectAccess<'de> {
187+
i: indexmap::map::IntoIter<Cow<'de, str>, Value<'de>>,
188+
v: Option<Value<'de>>,
189+
}
190+
191+
#[cfg(not(feature = "preserve_order"))]
184192
impl<'de, const N: usize> ObjectAccess<'de, N> {
185193
fn new(i: halfbrown::IntoIter<Cow<'de, str>, Value<'de>, N>) -> Self {
186194
Self { i, v: None }
187195
}
188196
}
189197

198+
#[cfg(feature = "preserve_order")]
199+
impl<'de> ObjectAccess<'de> {
200+
fn new(i: indexmap::map::IntoIter<Cow<'de, str>, Value<'de>>) -> Self {
201+
Self { i, v: None }
202+
}
203+
}
204+
190205
// `MapAccess` is provided to the `Visitor` to give it the ability to iterate
191206
// through entries of the map.
192207
impl<'de> MapAccess<'de> for ObjectAccess<'de> {
@@ -216,16 +231,32 @@ impl<'de> MapAccess<'de> for ObjectAccess<'de> {
216231
}
217232
}
218233

234+
#[cfg(not(feature = "preserve_order"))]
219235
struct ObjectRefAccess<'de> {
220236
i: halfbrown::Iter<'de, Cow<'de, str>, Value<'de>>,
221237
v: Option<&'de Value<'de>>,
222238
}
239+
240+
#[cfg(feature = "preserve_order")]
241+
struct ObjectRefAccess<'de> {
242+
i: indexmap::map::Iter<'de, Cow<'de, str>, Value<'de>>,
243+
v: Option<&'de Value<'de>>,
244+
}
245+
246+
#[cfg(not(feature = "preserve_order"))]
223247
impl<'de> ObjectRefAccess<'de> {
224248
fn new(i: halfbrown::Iter<'de, Cow<'de, str>, Value<'de>>) -> Self {
225249
Self { i, v: None }
226250
}
227251
}
228252

253+
#[cfg(feature = "preserve_order")]
254+
impl<'de> ObjectRefAccess<'de> {
255+
fn new(i: indexmap::map::Iter<'de, Cow<'de, str>, Value<'de>>) -> Self {
256+
Self { i, v: None }
257+
}
258+
}
259+
229260
// `MapAccess` is provided to the `Visitor` to give it the ability to iterate
230261
// through entries of the map.
231262
impl<'de> MapAccess<'de> for ObjectRefAccess<'de> {

src/serde/value/borrowed/se.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,12 @@ impl<'se> serde::Serializer for Serializer<'se> {
194194
{
195195
let mut values = Object::with_capacity_and_hasher(1, ObjectHasher::default());
196196
let x = stry!(to_value(value));
197-
unsafe { values.insert_nocheck(variant.into(), x) };
197+
#[cfg(not(feature = "preserve_order"))]
198+
unsafe {
199+
values.insert_nocheck(variant.into(), x);
200+
};
201+
#[cfg(feature = "preserve_order")]
202+
values.insert(variant.into(), x);
198203
Ok(Value::from(values))
199204
}
200205

@@ -349,7 +354,12 @@ impl<'se> serde::ser::SerializeTupleVariant for SerializeTupleVariant<'se> {
349354

350355
fn end(self) -> Result<Value<'se>> {
351356
let mut object = Object::with_capacity_and_hasher(1, ObjectHasher::default());
352-
unsafe { object.insert_nocheck(self.name.into(), Value::Array(Box::new(self.vec))) };
357+
#[cfg(not(feature = "preserve_order"))]
358+
unsafe {
359+
object.insert_nocheck(self.name.into(), Value::Array(Box::new(self.vec)))
360+
};
361+
#[cfg(feature = "preserve_order")]
362+
object.insert(self.name.into(), Value::Array(Box::new(self.vec)));
353363

354364
Ok(Value::Object(Box::new(object)))
355365
}
@@ -594,7 +604,12 @@ impl<'se> serde::ser::SerializeStructVariant for SerializeStructVariant<'se> {
594604

595605
fn end(self) -> Result<Value<'se>> {
596606
let mut object = Object::with_capacity_and_hasher(1, ObjectHasher::default());
597-
unsafe { object.insert_nocheck(self.name.into(), self.map.into()) };
607+
#[cfg(not(feature = "preserve_order"))]
608+
unsafe {
609+
object.insert_nocheck(self.name.into(), self.map.into())
610+
};
611+
#[cfg(feature = "preserve_order")]
612+
object.insert(self.name.into(), self.map.into());
598613
Ok(Value::Object(Box::new(object)))
599614
}
600615
}

src/serde/value/owned/de.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,32 @@ impl<'de> SeqAccess<'de> for ArrayRef<'de> {
164164
}
165165
}
166166

167+
#[cfg(not(feature = "preserve_order"))]
167168
struct ObjectAccess<const N: usize = 32> {
168169
i: halfbrown::IntoIter<String, Value, N>,
169170
v: Option<Value>,
170171
}
171172

173+
#[cfg(feature = "preserve_order")]
174+
struct ObjectAccess {
175+
i: indexmap::map::IntoIter<String, Value>,
176+
v: Option<Value>,
177+
}
178+
179+
#[cfg(not(feature = "preserve_order"))]
172180
impl<const N: usize> ObjectAccess<N> {
173181
fn new(i: halfbrown::IntoIter<String, Value, N>) -> Self {
174182
Self { i, v: None }
175183
}
176184
}
185+
186+
#[cfg(feature = "preserve_order")]
187+
impl ObjectAccess {
188+
fn new(i: indexmap::map::IntoIter<String, Value>) -> Self {
189+
Self { i, v: None }
190+
}
191+
}
192+
177193
// `MapAccess` is provided to the `Visitor` to give it the ability to iterate
178194
// through entries of the map.
179195
impl<'de> MapAccess<'de> for ObjectAccess {
@@ -203,17 +219,32 @@ impl<'de> MapAccess<'de> for ObjectAccess {
203219
}
204220
}
205221

222+
#[cfg(not(feature = "preserve_order"))]
206223
struct ObjectRefAccess<'de> {
207224
i: halfbrown::Iter<'de, String, Value>,
208225
v: Option<&'de Value>,
209226
}
210227

228+
#[cfg(feature = "preserve_order")]
229+
struct ObjectRefAccess<'de> {
230+
i: indexmap::map::Iter<'de, String, Value>,
231+
v: Option<&'de Value>,
232+
}
233+
234+
#[cfg(not(feature = "preserve_order"))]
211235
impl<'de> ObjectRefAccess<'de> {
212236
fn new(i: halfbrown::Iter<'de, String, Value>) -> Self {
213237
Self { i, v: None }
214238
}
215239
}
216240

241+
#[cfg(feature = "preserve_order")]
242+
impl<'de> ObjectRefAccess<'de> {
243+
fn new(i: indexmap::map::Iter<'de, String, Value>) -> Self {
244+
Self { i, v: None }
245+
}
246+
}
247+
217248
// `MapAccess` is provided to the `Visitor` to give it the ability to iterate
218249
// through entries of the map.
219250
impl<'de> MapAccess<'de> for ObjectRefAccess<'de> {

src/serde/value/owned/se.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,12 @@ impl serde::Serializer for Serializer {
180180
T: ?Sized + Serialize,
181181
{
182182
let mut values = Object::with_capacity_and_hasher(1, ObjectHasher::default());
183-
unsafe { values.insert_nocheck(variant.into(), stry!(to_value(value))) };
183+
#[cfg(not(feature = "preserve_order"))]
184+
unsafe {
185+
values.insert_nocheck(variant.into(), stry!(to_value(value)))
186+
};
187+
#[cfg(feature = "preserve_order")]
188+
values.insert(variant.into(), stry!(to_value(value)));
184189
Ok(Value::from(values))
185190
}
186191

@@ -335,7 +340,12 @@ impl serde::ser::SerializeTupleVariant for SerializeTupleVariant {
335340

336341
fn end(self) -> Result<Value> {
337342
let mut object = Object::with_capacity_and_hasher(1, ObjectHasher::default());
338-
unsafe { object.insert_nocheck(self.name, Value::Array(Box::new(self.vec))) };
343+
#[cfg(not(feature = "preserve_order"))]
344+
unsafe {
345+
object.insert_nocheck(self.name, Value::Array(Box::new(self.vec)))
346+
};
347+
#[cfg(feature = "preserve_order")]
348+
object.insert(self.name, Value::Array(Box::new(self.vec)));
339349
Ok(Value::from(object))
340350
}
341351
}
@@ -574,7 +584,12 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant {
574584

575585
fn end(self) -> Result<Value> {
576586
let mut object = Object::with_capacity_and_hasher(1, ObjectHasher::default());
577-
unsafe { object.insert_nocheck(self.name, Value::from(self.map)) };
587+
#[cfg(not(feature = "preserve_order"))]
588+
unsafe {
589+
object.insert_nocheck(self.name, Value::from(self.map))
590+
};
591+
#[cfg(feature = "preserve_order")]
592+
object.insert(self.name, Value::from(self.map));
578593
Ok(Value::from(object))
579594
}
580595
}

src/value.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ pub use self::owned::{
6868
to_value_with_buffers as to_owned_value_with_buffers,
6969
};
7070
use crate::{Buffers, Deserializer, Result};
71+
#[cfg(not(feature = "preserve_order"))]
7172
use halfbrown::HashMap;
73+
#[cfg(feature = "preserve_order")]
74+
use indexmap::IndexMap;
7275
use std::hash::Hash;
7376
use std::marker::PhantomData;
7477
use tape::Node;
@@ -78,8 +81,18 @@ pub use value_trait::*;
7881
#[cfg(feature = "known-key")]
7982
pub type ObjectHasher = crate::known_key::NotSoRandomState;
8083
/// Hasher used for objects
81-
#[cfg(not(feature = "known-key"))]
84+
#[cfg(all(not(feature = "known-key"), not(feature = "preserve_order")))]
8285
pub type ObjectHasher = halfbrown::DefaultHashBuilder;
86+
/// Hasher used for objects
87+
#[cfg(all(not(feature = "known-key"), feature = "preserve_order"))]
88+
pub type ObjectHasher = std::hash::RandomState;
89+
90+
/// Hashmap used for objects
91+
#[cfg(not(feature = "preserve_order"))]
92+
type ObjectMap<K, V> = HashMap<K, V, ObjectHasher>;
93+
/// Hashmap used for objects
94+
#[cfg(feature = "preserve_order")]
95+
type ObjectMap<K, V> = IndexMap<K, V, ObjectHasher>;
8396

8497
/// Parses a slice of bytes into a Value dom.
8598
///
@@ -92,7 +105,7 @@ pub type ObjectHasher = halfbrown::DefaultHashBuilder;
92105
/// Will return `Err` if `s` is invalid JSON.
93106
pub fn deserialize<'de, Value, Key>(s: &'de mut [u8]) -> Result<Value>
94107
where
95-
Value: ValueBuilder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + 'de,
108+
Value: ValueBuilder<'de> + From<Vec<Value>> + From<ObjectMap<Key, Value>> + 'de,
96109
Key: Hash + Eq + From<&'de str>,
97110
{
98111
match Deserializer::from_slice(s) {
@@ -117,7 +130,7 @@ pub fn deserialize_with_buffers<'de, Value, Key>(
117130
buffers: &mut Buffers,
118131
) -> Result<Value>
119132
where
120-
Value: ValueBuilder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + 'de,
133+
Value: ValueBuilder<'de> + From<Vec<Value>> + From<ObjectMap<Key, Value>> + 'de,
121134
Key: Hash + Eq + From<&'de str>,
122135
{
123136
match Deserializer::from_slice_with_buffers(s, buffers) {
@@ -128,7 +141,7 @@ where
128141

129142
struct ValueDeserializer<'de, Value, Key>
130143
where
131-
Value: ValueBuilder<'de> + From<Vec<Value>> + From<HashMap<Key, Value, ObjectHasher>> + 'de,
144+
Value: ValueBuilder<'de> + From<Vec<Value>> + From<ObjectMap<Key, Value>> + 'de,
132145
Key: Hash + Eq + From<&'de str>,
133146
{
134147
de: Deserializer<'de>,
@@ -140,7 +153,7 @@ where
140153
Value: ValueBuilder<'de>
141154
+ From<&'de str>
142155
+ From<Vec<Value>>
143-
+ From<HashMap<Key, Value, ObjectHasher>>
156+
+ From<ObjectMap<Key, Value>>
144157
+ 'de,
145158
Key: Hash + Eq + From<&'de str>,
146159
{
@@ -179,18 +192,18 @@ where
179192

180193
#[cfg_attr(not(feature = "no-inline"), inline)]
181194
fn parse_map(&mut self, len: usize) -> Value {
182-
let mut res: HashMap<Key, Value, ObjectHasher> =
183-
HashMap::with_capacity_and_hasher(len, ObjectHasher::default());
195+
let mut res: ObjectMap<Key, Value> =
196+
ObjectMap::with_capacity_and_hasher(len, ObjectHasher::default());
184197

185198
// Since we checked if it's empty we know that we at least have one
186199
// element so we eat this
187200
for _ in 0..len {
188201
if let Node::String(key) = unsafe { self.de.next_() } {
189-
#[cfg(not(feature = "value-no-dup-keys"))]
202+
#[cfg(all(not(feature = "value-no-dup-keys"), not(feature = "preserve_order")))]
190203
unsafe {
191204
res.insert_nocheck(key.into(), self.parse());
192205
};
193-
#[cfg(feature = "value-no-dup-keys")]
206+
#[cfg(any(feature = "value-no-dup-keys", feature = "preserve_order"))]
194207
res.insert(key.into(), self.parse());
195208
} else {
196209
unreachable!("parse_map: key needs to be a string");

0 commit comments

Comments
 (0)