fixed implementation of item.merge()

This commit is contained in:
Sebastian Moser
2024-06-08 14:59:05 +02:00
parent 11c0f7e00e
commit 2993beb788
2 changed files with 56 additions and 35 deletions

View File

@@ -45,11 +45,12 @@ impl<S: Store> Item<'_, S> {
self.instance.store.get_value_data_full(self.id()) self.instance.store.get_value_data_full(self.id())
} }
pub fn merge<V: Into<ItemData>>(&mut self, mut value: V) -> MizeResult<()> { pub fn merge<V: Into<ItemData>>(&mut self, mut value: V) -> MizeResult<()> {
//trace!("[ {} ] Item.merge()", "CALL".yellow());
let mut old_data = self.instance.store.get_value_data_full(self.id())?; let mut old_data = self.instance.store.get_value_data_full(self.id())?;
//trace!("old_data: {:?}", old_data);
old_data.merge(value.into()); let new_data = value.into();
//trace!("new_data: {:?}", old_data);
old_data.merge(new_data);
self.instance.store.set(self.id(), old_data)?; self.instance.store.set(self.id(), old_data)?;
Ok(()) Ok(())
} }
@@ -69,7 +70,7 @@ impl ItemData {
} }
pub fn merge(&mut self, other: ItemData) { pub fn merge(&mut self, other: ItemData) {
item_data_merge(self, other) item_data_merge(&mut self.0, &other.0);
} }
pub fn null() -> CborValue { pub fn null() -> CborValue {
@@ -176,39 +177,60 @@ fn item_data_set_path(data: &mut CborValue, path: Vec<String>, data_to_set: &Cbo
return Err(MizeError::new().msg("unreachable")); return Err(MizeError::new().msg("unreachable"));
} }
fn item_data_merge(first: &mut ItemData, other: ItemData){ fn item_data_merge(merge_into: &mut CborValue, other: &CborValue){
//trace!("[ {} ] item_data_merge()", "CALL".yellow()); // needs to be recursive
//trace!("[ {} ] first: {}", "ARG".yellow(), first.clone().into_item_data());
//trace!("[ {} ] other: {}", "ARG".yellow(), other.clone().into_item_data());
match first.0 { match (merge_into, other) {
CborValue::Map(ref mut map) => { // if both are maps
//trace!("data is a map: {:?}", map); // merge the keys/vals in the maps and call recursively on them
match other.0 { (CborValue::Map(ref mut merge_into_map), CborValue::Map(ref other_map)) => {
CborValue::Map(mut other_map) => { // go through other_map and merge those keys/values to merge_into
let mut to_add = Vec::new(); for (other_key, other_val) in other_map {
for (other_key, other_val) in other_map.clone() {
let mut key_found_in_old = false; // so find that same vale in merge_into, if exists recursively merge, else just add to
for (key, mut val) in map.clone() { // vec
if key == other_key { let mut found_value = CborValue::Null;
val = other_val.clone(); let mut value_found = false;
key_found_in_old = true; let mut new_value_for_merge_into: Vec<(CborValue, CborValue)> = Vec::new(); // here we collect the
} // new contents of the
} // map, to assign later
if key_found_in_old == false { // to merge_into_map
to_add.push((other_key.clone(), other_val.clone()));
} for (merge_into_key, merge_into_val) in merge_into_map.clone() {
if merge_into_key == *other_key {
value_found = true;
found_value = merge_into_val.to_owned();
// if we found it, also don't add it to new_value_for_merge_into
} else {
//if not found push to new_value_for_merge_into
new_value_for_merge_into.push((merge_into_key.to_owned(), merge_into_val.to_owned()));
} }
other_map.extend(to_add);
},
_ => {
*first = other;
} }
if value_found {
// we found it so merge and asign
item_data_merge(&mut found_value, other_val);
// to asign push to new_value_for_merge_into, because the old was removed already
new_value_for_merge_into.push((other_key.to_owned(), found_value));
} else {
// if not found, just add the other_key/val to new_value_for_merge_into
new_value_for_merge_into.push((other_key.to_owned(), other_val.to_owned()));
}
// finally, we need to asign the new_value_for_merge_into into merge_into
*merge_into_map = new_value_for_merge_into;
} }
}, }
_ => {
*first = other;
}, // in any other case we just want to set merge_into to other
// also this is the base case
(merge_into, other) => {
*merge_into = other.to_owned();
}
} }
} }

View File

@@ -98,7 +98,6 @@ fn config_from_string(config_string: String) -> MizeResult<ItemData> {
.ok_or(MizeError::new().msg(format!("Failed to parse Option: option '{}' has an empty value (thing after =)", option)))?; .ok_or(MizeError::new().msg(format!("Failed to parse Option: option '{}' has an empty value (thing after =)", option)))?;
let mut path_vec = vec!["config"]; let mut path_vec = vec!["config"];
path_vec.extend(path.split(".")); path_vec.extend(path.split("."));
println!("path_vec: {:?}", path_vec);
config.set_path(path_vec, ItemData::parse(value))?; config.set_path(path_vec, ItemData::parse(value))?;
} }