#[derive(Debug)]
pub enum Necessity<T> {
Optional(T),
Mandatory(T),
}
impl<T: std::cmp::PartialEq> std::cmp::PartialEq for Necessity<T> {
fn eq(&self, other: &Necessity<T>) -> bool {
if std::mem::discriminant(self) != std::mem::discriminant(other) {
return false;
}
self.inner_t() == other.inner_t()
}
}
impl<T> Necessity<T> {
pub fn into_inner_t(self) -> T {
match self {
Necessity::Optional(t) => t,
Necessity::Mandatory(t) => t,
}
}
pub fn inner_t(&self) -> &T {
match self {
Necessity::Optional(t) => t,
Necessity::Mandatory(t) => t,
}
}
pub fn inner_t_mut(&mut self) -> &mut T {
match self {
Necessity::Optional(t) => t,
Necessity::Mandatory(t) => t,
}
}
}
pub fn merge_necessity<T: std::cmp::PartialEq>(
vec: Vec<Necessity<T>>,
other: Vec<Necessity<T>>,
) -> Vec<Necessity<T>> {
let mut result: Vec<Necessity<T>> = Vec::new();
for vec_item in vec.into_iter() {
let mut found = false;
let mut optional = true;
for other_item in other.iter() {
if other_item.inner_t() == vec_item.inner_t() {
found = true;
if let (Necessity::Mandatory(_), Necessity::Mandatory(_)) = (&other_item, &vec_item)
{
optional = false
}
break;
}
}
match found {
true => match optional {
true => result.push(Necessity::Optional(vec_item.into_inner_t())),
false => result.push(Necessity::Mandatory(vec_item.into_inner_t())),
},
false => result.push(Necessity::Optional(vec_item.into_inner_t())),
}
}
for other_item in other.into_iter().rev() {
let mut found = false;
for result_item in result.iter() {
if other_item.inner_t() == result_item.inner_t() {
found = true;
break;
}
}
match found {
true => (),
false => result.push(Necessity::Optional(other_item.into_inner_t())),
}
}
result
}
#[cfg(test)]
mod tests {
use crate::necessity::{merge_necessity, Necessity};
#[test]
fn merge_necessity_changes_necessity_states() {
let vec: Vec<Necessity<u8>> = vec![Necessity::Mandatory(1), Necessity::Mandatory(2)];
let other: Vec<Necessity<u8>> = vec![Necessity::Mandatory(1), Necessity::Mandatory(3)];
let expected: Vec<Necessity<u8>> = vec![
Necessity::Mandatory(1),
Necessity::Optional(2),
Necessity::Optional(3),
];
let actual = merge_necessity(vec, other);
assert_eq!(actual, expected);
}
#[test]
fn merge_necessity_keeps_optional() {
let vec: Vec<Necessity<u8>> = vec![
Necessity::Mandatory(1),
Necessity::Optional(2),
Necessity::Optional(3),
];
let other: Vec<Necessity<u8>> = vec![
Necessity::Mandatory(1),
Necessity::Mandatory(2),
Necessity::Optional(3),
];
let expected: Vec<Necessity<u8>> = vec![
Necessity::Mandatory(1),
Necessity::Optional(2),
Necessity::Optional(3),
];
let actual = merge_necessity(vec, other);
assert_eq!(actual, expected);
}
#[test]
fn merge_necessity_applies_optional() {
let vec: Vec<Necessity<u8>> = vec![Necessity::Mandatory(1), Necessity::Mandatory(2)];
let other: Vec<Necessity<u8>> = vec![Necessity::Mandatory(1), Necessity::Optional(2)];
let expected: Vec<Necessity<u8>> = vec![Necessity::Mandatory(1), Necessity::Optional(2)];
let actual = merge_necessity(vec, other);
assert_eq!(actual, expected);
}
}