use super::ConflictResolutionChoice;
use crate::identified_vec_into_iterator::IdentifiedVecIntoIterator;
use crate::iterators::identified_vec_iterator::IdentifiedVecIterator;
use crate::Error;
use std::collections::HashMap;
use std::fmt::{Debug, Display};
use std::hash::{Hash, Hasher};
use super::is_identified_vec::IsIdentifiedVec;
#[derive(Debug, Clone)]
pub struct IdentifiedVec<I, E>
where
I: Eq + Hash + Clone + Debug,
{
pub(crate) order: Vec<I>,
pub(crate) elements: HashMap<I, E>,
pub(crate) _id_of_element: fn(&E) -> I,
}
impl<I, E> IsIdentifiedVec<E, I> for IdentifiedVec<I, E>
where
I: Eq + Hash + Clone + Debug,
{
#[inline]
fn new_identifying_element(id_of_element: fn(&E) -> I) -> Self {
Self {
order: Vec::new(),
elements: HashMap::new(),
_id_of_element: id_of_element,
}
}
#[cfg(not(tarpaulin_include))] #[inline]
fn try_from_iter_select_unique_ids_with<Er, It>(
elements: It,
id_of_element: fn(&E) -> I,
combine: fn((usize, &E, &E)) -> Result<ConflictResolutionChoice, Er>,
) -> Result<Self, Er>
where
It: IntoIterator<Item = E>,
{
let mut _order = Vec::<I>::new();
let mut _elements = HashMap::<I, E>::new();
for element in elements.into_iter() {
let id = id_of_element(&element);
match _elements.remove(&id) {
Some(existing) => match combine((_order.len(), &existing, &element)) {
Err(e) => return Err(e),
Ok(choice) => match choice {
ConflictResolutionChoice::ChooseFirst => {
_elements.insert(id.clone(), existing)
}
ConflictResolutionChoice::ChooseLast => {
_elements.insert(id.clone(), element)
}
},
},
None => {
_elements.insert(id.clone(), element);
_order.push(id);
None
}
};
}
Ok(Self {
order: _order,
_id_of_element: id_of_element,
elements: _elements,
})
}
#[cfg(not(tarpaulin_include))] #[inline]
fn from_iter_select_unique_ids_with<It>(
elements: It,
id_of_element: fn(&E) -> I,
combine: fn((usize, &E, &E)) -> ConflictResolutionChoice,
) -> Self
where
It: IntoIterator<Item = E>,
{
let mut _order = Vec::<I>::new();
let mut _elements = HashMap::<I, E>::new();
for element in elements.into_iter() {
let id = id_of_element(&element);
match _elements.remove(&id) {
Some(existing) => match combine((_order.len(), &existing, &element)) {
ConflictResolutionChoice::ChooseFirst => _elements.insert(id.clone(), existing),
ConflictResolutionChoice::ChooseLast => _elements.insert(id.clone(), element),
},
None => {
_elements.insert(id.clone(), element);
_order.push(id);
None
}
};
}
Self {
order: _order,
_id_of_element: id_of_element,
elements: _elements,
}
}
#[inline]
fn ids(&self) -> Vec<I> {
self.order.clone()
}
#[inline]
fn len(&self) -> usize {
if cfg!(debug_assertions) {
assert_eq!(self.order.len(), self.elements.len());
}
self.order.len()
}
#[inline]
fn index_of_id(&self, id: &I) -> Option<usize> {
self.order.iter().position(|i| i == id)
}
#[inline]
fn elements(&self) -> Vec<&E> {
self.iter().collect()
}
#[inline]
fn contains(&self, element: &E) -> bool {
self.elements.contains_key(&self.id(&element))
}
#[inline]
fn contains_id(&self, id: &I) -> bool {
self.elements.contains_key(id)
}
#[inline]
fn get(&self, id: &I) -> Option<&E> {
self.elements.get(id)
}
#[inline]
fn get_at_index(&self, index: usize) -> Option<&E> {
self.order.get(index).and_then(|id| self.get(id))
}
#[inline]
fn append(&mut self, element: E) -> (bool, usize) {
self.insert(element, self.end_index())
}
#[inline]
fn append_other<It>(&mut self, other: It)
where
It: IntoIterator<Item = E>,
{
other.into_iter().for_each(|i| _ = self.append(i))
}
#[inline]
fn update_or_append(&mut self, element: E) -> Option<E> {
let id = self.id(&element);
self._update_value(element, id)
}
#[inline]
fn update_at(&mut self, element: E, index: usize) -> E {
let old_id = self
.order
.get(index)
.expect("Expected element at index {index}");
let id = self.id(&element);
assert_eq!(
&id, old_id,
"The replacement item must match the identity of the original"
);
return self
._update_value_inserting_at(element, id, index)
.0
.expect("Replaced old value");
}
#[inline]
fn update_with<F>(&mut self, id: &I, mut mutate: F) -> bool
where
F: FnMut(&mut E),
{
if !self.contains_id(id) {
return false;
}
let mut existing = self.elements.remove(id).expect("Element for existing id");
mutate(&mut existing);
self.elements.insert(id.clone(), existing);
true
}
#[allow(unused_mut)]
#[inline]
fn try_update_with<F, Er>(&mut self, id: &I, mut mutate: F) -> Result<bool, Er>
where
F: FnMut(&mut E) -> Result<E, Er>,
{
if !self.contains_id(id) {
return Ok(false);
}
let mut existing = self.elements.remove(id).expect("Element for existing id");
mutate(&mut existing)
.map(|updated| {
self.elements.insert(id.clone(), updated);
true
})
.map_err(|e| {
self.elements.insert(id.clone(), existing);
e
})
}
#[inline]
fn try_update(&mut self, element: E) -> Result<E, Error> {
let id = self.id(&element);
if self.get(&id).is_none() {
return Err(Error::ExpectedElementNotPresent(format!("{:#?}", id)));
}
Ok(self
._update_value(element, id)
.expect("Failed to update value"))
}
#[cfg(not(tarpaulin_include))] #[inline]
fn insert(&mut self, element: E, at: usize) -> (bool, usize) {
let id = self.id(&element);
if let Some(existing) = self.index_of_id(&id) {
return (false, existing.clone());
}
self._update_value_inserting_at(element, id, at);
(true, at)
}
#[inline]
fn update_or_insert(&mut self, element: E, index: usize) -> (Option<E>, usize) {
let id = self.id(&element);
self._update_value_inserting_at(element, id, index)
}
#[cfg(not(tarpaulin_include))] #[inline]
fn remove_by_id(&mut self, id: &I) -> Option<E> {
match self.index_of_id(id) {
Some(index) => {
self.order.remove(index);
return self.elements.remove(id);
}
None => {
assert!(!self.elements.contains_key(id));
return None;
}
}
}
#[inline]
fn remove(&mut self, element: &E) -> Option<E> {
self.remove_by_id(&self.id(element))
}
#[inline]
fn remove_at(&mut self, index: usize) -> E {
let id = self
.order
.get(index)
.expect("Precondition failure, index out of bounds");
let removed = self.elements.remove(id).expect("E of existing id");
self.order.remove(index);
return removed;
}
#[inline]
fn remove_at_offsets<It>(&mut self, offsets: It)
where
It: IntoIterator<Item = usize>,
{
let mut internal_offset = 0;
offsets.into_iter().for_each(|i| {
_ = self.remove_at(i - internal_offset);
internal_offset += 1;
})
}
#[inline]
fn try_append_new(&mut self, element: E) -> Result<(bool, usize), Error> {
let id = self.id(&element);
if self.contains_id(&id) {
return Err(Error::ElementWithSameIDFound(format!("{:#?}", id)));
}
Ok(self.append(element))
}
#[inline]
fn iter(&self) -> IdentifiedVecIterator<I, E> {
IdentifiedVecIterator::new(self)
}
}
pub trait ItemsCloned<Element>
where
Element: Clone,
{
fn items(&self) -> Vec<Element>;
}
impl<I, E> ItemsCloned<E> for IdentifiedVec<I, E>
where
E: Clone,
I: Eq + Hash + Clone + Debug,
{
#[inline]
fn items(&self) -> Vec<E> {
self.iter().map(|e| e.clone()).collect()
}
}
impl<I, E> IntoIterator for IdentifiedVec<I, E>
where
I: Eq + Hash + Clone + Debug,
{
type Item = E;
type IntoIter = IdentifiedVecIntoIterator<I, E>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter::new(self)
}
}
impl<I, E> IdentifiedVec<I, E> where I: Eq + Hash + Clone + Debug {}
impl<I, E> PartialEq for IdentifiedVec<I, E>
where
E: PartialEq,
I: Eq + Hash + Clone + Debug,
{
fn eq(&self, other: &Self) -> bool {
self.elements() == other.elements()
}
}
impl<I, E> Eq for IdentifiedVec<I, E>
where
E: Eq,
I: Eq + Hash + Clone + Debug,
{
}
impl<I, E> Hash for IdentifiedVec<I, E>
where
E: Hash,
I: Eq + Hash + Clone + Debug,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.elements().hash(state);
}
}
impl<I, E> Display for IdentifiedVec<I, E>
where
E: Debug,
I: Eq + Hash + Clone + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.elements().fmt(f)
}
}
impl<I, E> IdentifiedVec<I, E>
where
I: Eq + Hash + Clone + Debug,
{
#[inline]
fn end_index(&self) -> usize {
self.len()
}
#[inline]
fn id(&self, of: &E) -> I {
(self._id_of_element)(of)
}
#[cfg(not(tarpaulin_include))] #[inline]
fn _insert_id_at(&mut self, id: I, index: usize) -> (bool, usize) {
match self.index_of_id(&id) {
Some(existing) => (false, existing),
None => {
self.order.insert(index, id);
(true, index)
}
}
}
#[inline]
fn _update_value(&mut self, element: E, for_key: I) -> Option<E> {
let value = element;
let key = for_key;
let maybe_old = self.elements.remove(&key);
self.elements.insert(key.clone(), value);
if maybe_old.is_some() {
return maybe_old;
} else {
self.order.push(key);
None
}
}
#[inline]
fn _update_value_inserting_at(
&mut self,
element: E,
for_key: I,
index: usize,
) -> (Option<E>, usize) {
let id = for_key;
let value = element;
let (inserted, offset) = self._insert_id_at(id.clone(), index);
if inserted {
assert_eq!(offset, index);
self.elements.insert(id.clone(), value);
return (None, offset);
}
let old = self.elements.remove(&id).expect("existing element");
self.elements.insert(id, value);
return (Some(old), offset);
}
}
impl<ID, Element> IdentifiedVec<ID, Element>
where
ID: Eq + Hash + Clone + Debug,
Element: Eq + Debug,
{
#[inline]
pub fn try_append_unique_element(&mut self, element: Element) -> Result<(bool, usize), Error> {
let id = self.id(&element);
if let Some(value) = self.get(&id) {
if value == &element {
return Err(Error::ElementWithSameValueFound(format!("{:?}", value)));
} else {
return Err(Error::ElementWithSameIDFound(format!("{:?}", id)));
}
}
Ok(self.append(element))
}
}