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