use std::{fmt, ops::Deref};
use super::ObservableVector;
pub struct ObservableVectorEntry<'a, T> {
inner: &'a mut ObservableVector<T>,
index: EntryIndex<'a>,
}
impl<'a, T> ObservableVectorEntry<'a, T>
where
T: Clone + Send + Sync + 'static,
{
pub(super) fn new(inner: &'a mut ObservableVector<T>, index: usize) -> Self {
Self { inner, index: EntryIndex::Owned(index) }
}
fn new_borrowed(inner: &'a mut ObservableVector<T>, index: &'a mut usize) -> Self {
Self { inner, index: EntryIndex::Borrowed(index) }
}
pub fn index(this: &Self) -> usize {
this.index.value()
}
pub fn set(this: &mut Self, value: T) -> T {
this.inner.set(this.index.value(), value)
}
pub fn remove(mut this: Self) -> T {
this.inner.remove(this.index.make_owned())
}
}
impl<T> fmt::Debug for ObservableVectorEntry<'_, T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let index = self.index.value();
f.debug_struct("ObservableVectorEntry")
.field("item", &self.inner[index])
.field("index", &index)
.finish()
}
}
impl<T> Deref for ObservableVectorEntry<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner[self.index.value()]
}
}
impl<T> Drop for ObservableVectorEntry<'_, T> {
fn drop(&mut self) {
if let EntryIndex::Borrowed(idx) = &mut self.index {
**idx += 1;
}
}
}
pub(super) enum EntryIndex<'a> {
Borrowed(&'a mut usize),
Owned(usize),
}
impl<'a> EntryIndex<'a> {
pub(super) fn value(&self) -> usize {
match self {
EntryIndex::Borrowed(idx) => **idx,
EntryIndex::Owned(idx) => *idx,
}
}
pub(super) fn make_owned(&mut self) -> usize {
match self {
EntryIndex::Borrowed(idx) => {
let idx = **idx;
*self = EntryIndex::Owned(idx);
idx
}
EntryIndex::Owned(idx) => *idx,
}
}
}
#[derive(Debug)]
pub struct ObservableVectorEntries<'a, T> {
inner: &'a mut ObservableVector<T>,
index: usize,
}
impl<'a, T> ObservableVectorEntries<'a, T>
where
T: Clone + Send + Sync + 'static,
{
pub(super) fn new(inner: &'a mut ObservableVector<T>) -> Self {
Self { inner, index: 0 }
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<ObservableVectorEntry<'_, T>> {
if self.index < self.inner.len() {
Some(ObservableVectorEntry::new_borrowed(self.inner, &mut self.index))
} else {
None
}
}
}