Skip to content

Commit 35b6643

Browse files
authored
Fix internal representation of object fields (#872, #926)
1 parent 70bc9c4 commit 35b6643

File tree

2 files changed

+53
-35
lines changed

2 files changed

+53
-35
lines changed

juniper/src/types/base.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,5 +617,41 @@ where
617617

618618
/// Merges `response_name`/`value` pair into `result`
619619
pub(crate) fn merge_key_into<S>(result: &mut Object<S>, response_name: &str, value: Value<S>) {
620+
if let Some(v) = result.get_mut_field_value(response_name) {
621+
match v {
622+
Value::Object(dest_obj) => {
623+
if let Value::Object(src_obj) = value {
624+
merge_maps(dest_obj, src_obj);
625+
}
626+
}
627+
Value::List(dest_list) => {
628+
if let Value::List(src_list) = value {
629+
dest_list
630+
.iter_mut()
631+
.zip(src_list.into_iter())
632+
.for_each(|(d, s)| {
633+
if let Value::Object(d_obj) = d {
634+
if let Value::Object(s_obj) = s {
635+
merge_maps(d_obj, s_obj);
636+
}
637+
}
638+
});
639+
}
640+
}
641+
_ => {}
642+
}
643+
return;
644+
}
620645
result.add_field(response_name, value);
621646
}
647+
648+
/// Merges `src` object's fields into `dest`
649+
fn merge_maps<S>(dest: &mut Object<S>, src: Object<S>) {
650+
for (key, value) in src {
651+
if dest.contains_field(&key) {
652+
merge_key_into(dest, &key, value);
653+
} else {
654+
dest.add_field(key, value);
655+
}
656+
}
657+
}

juniper/src/value/object.rs

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
1-
use std::iter::FromIterator;
1+
use std::{iter::FromIterator, mem};
22

33
use super::Value;
44
use indexmap::map::{IndexMap, IntoIter};
55

66
/// A Object value
7-
#[derive(Debug, Clone)]
7+
#[derive(Debug, Clone, PartialEq)]
88
pub struct Object<S> {
99
key_value_list: IndexMap<String, Value<S>>,
1010
}
1111

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-
}
18-
}
19-
2012
impl<S> Object<S> {
2113
/// Create a new Object value with a fixed number of
2214
/// preallocated slots for field-value pairs
@@ -35,28 +27,18 @@ impl<S> Object<S> {
3527
/// returned.
3628
pub fn add_field<K>(&mut self, k: K, value: Value<S>) -> Option<Value<S>>
3729
where
38-
K: Into<String>,
39-
for<'a> &'a str: PartialEq<K>,
30+
K: AsRef<str> + Into<String>,
4031
{
41-
let key: String = k.into();
42-
match (value, self.key_value_list.get_mut(&key)) {
43-
(Value::<S>::Object(obj_val), Some(Value::<S>::Object(existing_obj))) => {
44-
for (key, val) in obj_val.into_iter() {
45-
existing_obj.add_field::<String>(key, val);
46-
}
47-
None
48-
}
49-
(non_obj_val, _) => self.key_value_list.insert(key, non_obj_val),
32+
if let Some(v) = self.key_value_list.get_mut(k.as_ref()) {
33+
Some(mem::replace(v, value))
34+
} else {
35+
self.key_value_list.insert(k.into(), value)
5036
}
5137
}
5238

5339
/// Check if the object already contains a field with the given name
54-
pub fn contains_field<K>(&self, f: K) -> bool
55-
where
56-
K: Into<String>,
57-
for<'a> &'a str: PartialEq<K>,
58-
{
59-
self.key_value_list.contains_key(&f.into())
40+
pub fn contains_field<K: AsRef<str>>(&self, k: K) -> bool {
41+
self.key_value_list.contains_key(k.as_ref())
6042
}
6143

6244
/// Get a iterator over all field value pairs
@@ -75,12 +57,13 @@ impl<S> Object<S> {
7557
}
7658

7759
/// Get the value for a given field
78-
pub fn get_field_value<K>(&self, key: K) -> Option<&Value<S>>
79-
where
80-
K: Into<String>,
81-
for<'a> &'a str: PartialEq<K>,
82-
{
83-
self.key_value_list.get(&key.into())
60+
pub fn get_field_value<K: AsRef<str>>(&self, key: K) -> Option<&Value<S>> {
61+
self.key_value_list.get(key.as_ref())
62+
}
63+
64+
/// Get the mutable value for a given field
65+
pub fn get_mut_field_value<K: AsRef<str>>(&mut self, key: K) -> Option<&mut Value<S>> {
66+
self.key_value_list.get_mut(key.as_ref())
8467
}
8568
}
8669

@@ -101,8 +84,7 @@ impl<S> From<Object<S>> for Value<S> {
10184

10285
impl<K, S> FromIterator<(K, Value<S>)> for Object<S>
10386
where
104-
K: Into<String>,
105-
for<'a> &'a str: PartialEq<K>,
87+
K: AsRef<str> + Into<String>,
10688
{
10789
fn from_iter<I>(iter: I) -> Self
10890
where

0 commit comments

Comments
 (0)