Skip to content

Commit f5ce9f2

Browse files
abrackxLegNeato
andauthored
Switch to HashMap for the internal representation of object fields (#872)
* Resolves #818. Updates Object key_value_list to use HashMap<String, Value<S>>. Updates test cases. * Updates to use IndexMap. Reverts changes to test cases. Co-authored-by: Christian Legnitto <[email protected]>
1 parent f6523c9 commit f5ce9f2

File tree

6 files changed

+28
-112
lines changed

6 files changed

+28
-112
lines changed

integration_tests/async_await/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ async fn async_simple() {
9696

9797
assert!(errs.is_empty());
9898

99-
let mut obj = res.into_object().unwrap();
100-
obj.sort_by_field();
99+
let obj = res.into_object().unwrap();
101100
let value = Value::Object(obj);
102101

103102
assert_eq!(

juniper/src/executor_tests/async_await/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ async fn async_simple() {
9191

9292
assert!(errs.is_empty());
9393

94-
let mut obj = res.into_object().unwrap();
95-
obj.sort_by_field();
94+
let obj = res.into_object().unwrap();
9695
let value = Value::Object(obj);
9796

9897
assert_eq!(

juniper/src/integrations/serde.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ where
381381
{
382382
let mut map = serializer.serialize_map(Some(self.field_count()))?;
383383

384-
for &(ref f, ref v) in self.iter() {
384+
for (ref f, ref v) in self.iter() {
385385
map.serialize_key(f)?;
386386
map.serialize_value(v)?;
387387
}

juniper/src/types/base.rs

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -599,44 +599,5 @@ where
599599

600600
/// Merges `response_name`/`value` pair into `result`
601601
pub(crate) fn merge_key_into<S>(result: &mut Object<S>, response_name: &str, value: Value<S>) {
602-
if let Some(&mut (_, ref mut e)) = result
603-
.iter_mut()
604-
.find(|&&mut (ref key, _)| key == response_name)
605-
{
606-
match *e {
607-
Value::Object(ref mut dest_obj) => {
608-
if let Value::Object(src_obj) = value {
609-
merge_maps(dest_obj, src_obj);
610-
}
611-
}
612-
Value::List(ref mut dest_list) => {
613-
if let Value::List(src_list) = value {
614-
dest_list
615-
.iter_mut()
616-
.zip(src_list.into_iter())
617-
.for_each(|(d, s)| {
618-
if let Value::Object(ref mut d_obj) = *d {
619-
if let Value::Object(s_obj) = s {
620-
merge_maps(d_obj, s_obj);
621-
}
622-
}
623-
});
624-
}
625-
}
626-
_ => {}
627-
}
628-
return;
629-
}
630602
result.add_field(response_name, value);
631603
}
632-
633-
/// Merges `src` object's fields into `dest`
634-
fn merge_maps<S>(dest: &mut Object<S>, src: Object<S>) {
635-
for (key, value) in src {
636-
if dest.contains_field(&key) {
637-
merge_key_into(dest, &key, value);
638-
} else {
639-
dest.add_field(key, value);
640-
}
641-
}
642-
}

juniper/src/value/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<S: ScalarValue> ToInputValue<S> for Value<S> {
195195
),
196196
Value::Object(ref o) => InputValue::Object(
197197
o.iter()
198-
.map(|&(ref k, ref v)| {
198+
.map(|(k, v)| {
199199
(
200200
Spanning::unlocated(k.clone()),
201201
Spanning::unlocated(v.to_input_value()),

juniper/src/value/object.rs

Lines changed: 24 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
use std::{iter::FromIterator, vec::IntoIter};
1+
use std::iter::FromIterator;
22

33
use super::Value;
4+
use indexmap::map::{IndexMap, IntoIter};
45

56
/// A Object value
6-
#[derive(Debug, Clone, PartialEq)]
7+
#[derive(Debug, Clone)]
78
pub struct Object<S> {
8-
key_value_list: Vec<(String, Value<S>)>,
9+
key_value_list: IndexMap<String, Value<S>>,
10+
}
11+
12+
impl<S: PartialEq> PartialEq for Object<S> {
13+
fn eq(&self, _: &Object<S>) -> bool {
14+
match self {
15+
Object { key_value_list } => self.key_value_list == *key_value_list,
16+
}
17+
}
918
}
1019

1120
impl<S> Object<S> {
1221
/// Create a new Object value with a fixed number of
1322
/// preallocated slots for field-value pairs
1423
pub fn with_capacity(size: usize) -> Self {
1524
Object {
16-
key_value_list: Vec::with_capacity(size),
25+
key_value_list: IndexMap::with_capacity(size),
1726
}
1827
}
1928

@@ -26,39 +35,26 @@ impl<S> Object<S> {
2635
K: Into<String>,
2736
for<'a> &'a str: PartialEq<K>,
2837
{
29-
if let Some(item) = self
30-
.key_value_list
31-
.iter_mut()
32-
.find(|&&mut (ref key, _)| (key as &str) == k)
33-
{
34-
return Some(::std::mem::replace(&mut item.1, value));
35-
}
36-
self.key_value_list.push((k.into(), value));
37-
None
38+
self.key_value_list.insert(k.into(), value)
3839
}
3940

4041
/// Check if the object already contains a field with the given name
4142
pub fn contains_field<K>(&self, f: K) -> bool
4243
where
44+
K: Into<String>,
4345
for<'a> &'a str: PartialEq<K>,
4446
{
45-
self.key_value_list
46-
.iter()
47-
.any(|&(ref key, _)| (key as &str) == f)
47+
self.key_value_list.contains_key(&f.into())
4848
}
4949

5050
/// Get a iterator over all field value pairs
51-
pub fn iter(&self) -> impl Iterator<Item = &(String, Value<S>)> {
52-
FieldIter {
53-
inner: self.key_value_list.iter(),
54-
}
51+
pub fn iter(&self) -> impl Iterator<Item = (&String, &Value<S>)> {
52+
self.key_value_list.iter()
5553
}
5654

5755
/// Get a iterator over all mutable field value pairs
58-
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut (String, Value<S>)> {
59-
FieldIterMut {
60-
inner: self.key_value_list.iter_mut(),
61-
}
56+
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&String, &mut Value<S>)> {
57+
self.key_value_list.iter_mut()
6258
}
6359

6460
/// Get the current number of fields
@@ -69,29 +65,16 @@ impl<S> Object<S> {
6965
/// Get the value for a given field
7066
pub fn get_field_value<K>(&self, key: K) -> Option<&Value<S>>
7167
where
68+
K: Into<String>,
7269
for<'a> &'a str: PartialEq<K>,
7370
{
74-
self.key_value_list
75-
.iter()
76-
.find(|&&(ref k, _)| (k as &str) == key)
77-
.map(|&(_, ref value)| value)
78-
}
79-
80-
/// Recursively sort all keys by field.
81-
pub fn sort_by_field(&mut self) {
82-
self.key_value_list
83-
.sort_by(|(key1, _), (key2, _)| key1.cmp(key2));
84-
for (_, ref mut value) in &mut self.key_value_list {
85-
if let Value::Object(ref mut o) = value {
86-
o.sort_by_field();
87-
}
88-
}
71+
self.key_value_list.get(&key.into())
8972
}
9073
}
9174

9275
impl<S> IntoIterator for Object<S> {
9376
type Item = (String, Value<S>);
94-
type IntoIter = IntoIter<Self::Item>;
77+
type IntoIter = IntoIter<String, Value<S>>;
9578

9679
fn into_iter(self) -> Self::IntoIter {
9780
self.key_value_list.into_iter()
@@ -115,37 +98,11 @@ where
11598
{
11699
let iter = iter.into_iter();
117100
let mut ret = Self {
118-
key_value_list: Vec::with_capacity(iter.size_hint().0),
101+
key_value_list: IndexMap::with_capacity(iter.size_hint().0),
119102
};
120103
for (k, v) in iter {
121104
ret.add_field(k, v);
122105
}
123106
ret
124107
}
125108
}
126-
127-
#[doc(hidden)]
128-
pub struct FieldIter<'a, S: 'a> {
129-
inner: ::std::slice::Iter<'a, (String, Value<S>)>,
130-
}
131-
132-
impl<'a, S> Iterator for FieldIter<'a, S> {
133-
type Item = &'a (String, Value<S>);
134-
135-
fn next(&mut self) -> Option<Self::Item> {
136-
self.inner.next()
137-
}
138-
}
139-
140-
#[doc(hidden)]
141-
pub struct FieldIterMut<'a, S: 'a> {
142-
inner: ::std::slice::IterMut<'a, (String, Value<S>)>,
143-
}
144-
145-
impl<'a, S> Iterator for FieldIterMut<'a, S> {
146-
type Item = &'a mut (String, Value<S>);
147-
148-
fn next(&mut self) -> Option<Self::Item> {
149-
self.inner.next()
150-
}
151-
}

0 commit comments

Comments
 (0)