Fix internal representation of object fields (#872, #926)

This commit is contained in:
xDarksome 2021-05-10 14:36:38 +03:00 committed by GitHub
parent 70bc9c4512
commit 35b6643bad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 35 deletions

View file

@ -617,5 +617,41 @@ where
/// Merges `response_name`/`value` pair into `result`
pub(crate) fn merge_key_into<S>(result: &mut Object<S>, response_name: &str, value: Value<S>) {
if let Some(v) = result.get_mut_field_value(response_name) {
match v {
Value::Object(dest_obj) => {
if let Value::Object(src_obj) = value {
merge_maps(dest_obj, src_obj);
}
}
Value::List(dest_list) => {
if let Value::List(src_list) = value {
dest_list
.iter_mut()
.zip(src_list.into_iter())
.for_each(|(d, s)| {
if let Value::Object(d_obj) = d {
if let Value::Object(s_obj) = s {
merge_maps(d_obj, s_obj);
}
}
});
}
}
_ => {}
}
return;
}
result.add_field(response_name, value);
}
/// Merges `src` object's fields into `dest`
fn merge_maps<S>(dest: &mut Object<S>, src: Object<S>) {
for (key, value) in src {
if dest.contains_field(&key) {
merge_key_into(dest, &key, value);
} else {
dest.add_field(key, value);
}
}
}

View file

@ -1,22 +1,14 @@
use std::iter::FromIterator;
use std::{iter::FromIterator, mem};
use super::Value;
use indexmap::map::{IndexMap, IntoIter};
/// A Object value
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub struct Object<S> {
key_value_list: IndexMap<String, Value<S>>,
}
impl<S: PartialEq> PartialEq for Object<S> {
fn eq(&self, _: &Object<S>) -> bool {
match self {
Object { key_value_list } => self.key_value_list == *key_value_list,
}
}
}
impl<S> Object<S> {
/// Create a new Object value with a fixed number of
/// preallocated slots for field-value pairs
@ -35,28 +27,18 @@ impl<S> Object<S> {
/// returned.
pub fn add_field<K>(&mut self, k: K, value: Value<S>) -> Option<Value<S>>
where
K: Into<String>,
for<'a> &'a str: PartialEq<K>,
K: AsRef<str> + Into<String>,
{
let key: String = k.into();
match (value, self.key_value_list.get_mut(&key)) {
(Value::<S>::Object(obj_val), Some(Value::<S>::Object(existing_obj))) => {
for (key, val) in obj_val.into_iter() {
existing_obj.add_field::<String>(key, val);
}
None
}
(non_obj_val, _) => self.key_value_list.insert(key, non_obj_val),
if let Some(v) = self.key_value_list.get_mut(k.as_ref()) {
Some(mem::replace(v, value))
} else {
self.key_value_list.insert(k.into(), value)
}
}
/// Check if the object already contains a field with the given name
pub fn contains_field<K>(&self, f: K) -> bool
where
K: Into<String>,
for<'a> &'a str: PartialEq<K>,
{
self.key_value_list.contains_key(&f.into())
pub fn contains_field<K: AsRef<str>>(&self, k: K) -> bool {
self.key_value_list.contains_key(k.as_ref())
}
/// Get a iterator over all field value pairs
@ -75,12 +57,13 @@ impl<S> Object<S> {
}
/// Get the value for a given field
pub fn get_field_value<K>(&self, key: K) -> Option<&Value<S>>
where
K: Into<String>,
for<'a> &'a str: PartialEq<K>,
{
self.key_value_list.get(&key.into())
pub fn get_field_value<K: AsRef<str>>(&self, key: K) -> Option<&Value<S>> {
self.key_value_list.get(key.as_ref())
}
/// Get the mutable value for a given field
pub fn get_mut_field_value<K: AsRef<str>>(&mut self, key: K) -> Option<&mut Value<S>> {
self.key_value_list.get_mut(key.as_ref())
}
}
@ -101,8 +84,7 @@ impl<S> From<Object<S>> for Value<S> {
impl<K, S> FromIterator<(K, Value<S>)> for Object<S>
where
K: Into<String>,
for<'a> &'a str: PartialEq<K>,
K: AsRef<str> + Into<String>,
{
fn from_iter<I>(iter: I) -> Self
where