use crate::{Optionable, OptionableConvert};
pub fn try_merge_optioned_set<TARGET, OTHER, T>(
target: &mut TARGET,
other: OTHER,
) -> Result<(), crate::Error>
where
TARGET: Extend<T>,
for<'a> &'a TARGET: IntoIterator<Item = &'a T>,
OTHER: IntoIterator<Item = T::Optioned>,
T: OptionableConvert + PartialEq,
T::Optioned: Sized,
{
for el in other {
let el = T::try_from_optioned(el)?;
if !target.into_iter().any(|el_target| &el == el_target) {
target.extend(Some(el));
}
}
Ok(())
}
pub trait OptionableMapKeysEq: Optionable {
fn keys_eq(&self, other: &Self::Optioned) -> bool;
}
pub fn try_merge_optioned_map<TARGET, OTHER, T>(
target: &mut TARGET,
other: OTHER,
) -> Result<(), crate::Error>
where
TARGET: Extend<T>,
for<'a> &'a mut TARGET: IntoIterator<Item = &'a mut T>,
OTHER: IntoIterator<Item = T::Optioned>,
T: OptionableConvert + OptionableMapKeysEq,
T::Optioned: Sized,
{
for el in other {
if let Some(el_target) = target.into_iter().find(|el_target| el_target.keys_eq(&el)) {
el_target.merge(el)?;
} else {
target.extend(Some(T::try_from_optioned(el)?));
}
}
Ok(())
}
#[cfg(feature = "std")]
#[cfg(test)]
mod test {
#[test]
fn merge_set() {
let mut target = vec![0, 1, 2];
super::try_merge_optioned_set(&mut target, vec![3]).unwrap();
assert_eq!(&target, &vec![0, 1, 2, 3]);
super::try_merge_optioned_set(&mut target, vec![0, 2, 4, 6, 8]).unwrap();
assert_eq!(&target, &vec![0, 1, 2, 3, 4, 6, 8]);
super::try_merge_optioned_set(&mut target, vec![0, 5, 9]).unwrap();
assert_eq!(&target, &vec![0, 1, 2, 3, 4, 6, 8, 5, 9]);
}
}