use super::{
grid::{Mut, Ref},
index::Index,
};
use crate::{Data, Key};
use ahash::AHashSet;
use std::{any::TypeId, hash::Hash};
#[derive(Debug)]
enum TableView<'a> {
Ref(Ref<'a>),
Mut { refs: Ref<'a>, muts: Mut<'a>, write: AHashSet<TypeId> },
}
impl<'a> TableView<'a> {
pub fn len_cols(&self) -> usize {
match self {
TableView::Ref(x) => x.len_cols(),
TableView::Mut { refs, muts, write } => {
refs.len_cols() + muts.len_rows() + write.len()
}
}
}
pub fn has_cols(&self) -> bool {
match self {
TableView::Ref(x) => x.has_cols(),
TableView::Mut { refs, muts, write } => {
refs.has_cols() || muts.has_cols() || !write.is_empty()
}
}
}
pub fn contains<T: Data>(&self) -> bool {
match self {
TableView::Ref(x) => x.contains::<T>(),
TableView::Mut { refs, muts, write } => {
refs.contains::<T>() || muts.contains::<T>() || write.contains(&T::ID)
}
}
}
pub fn contains_type(&self, id: &TypeId) -> bool {
match self {
TableView::Ref(x) => x.contains_type(id),
TableView::Mut { refs, muts, write } => {
refs.contains_type(id) || muts.contains_type(id) || write.contains(id)
}
}
}
pub fn is_readable<T: Data>(&self) -> bool {
match self {
TableView::Ref(x) => x.contains::<T>(),
TableView::Mut { refs, muts, .. } => {
refs.contains::<T>() || muts.contains::<T>()
}
}
}
pub fn is_writable<T: Data>(&self) -> bool {
if let TableView::Mut { muts, .. } = self {
muts.contains::<T>()
} else {
false
}
}
pub fn read<T: Data>(&mut self) -> Option<&'a [T]> {
match self {
TableView::Ref(x) => x.read::<T>(),
TableView::Mut { refs, muts, .. } => muts.read::<T>(refs),
}
}
pub fn write<T: Data>(&mut self) -> Option<&'a mut [T]> {
if let TableView::Mut { muts, write, .. } = self {
muts.write::<T>().map(|x| {
write.insert(T::ID);
x
})
} else {
None
}
}
}
#[derive(Debug)]
pub struct View<'a, K> {
index: &'a Index<K>,
grid: TableView<'a>,
}
impl<'a, K> View<'a, K> {
pub(in crate::table) fn new_ref(index: &'a Index<K>, refs: Ref<'a>) -> Self {
Self { index, grid: TableView::Ref(refs) }
}
pub(in crate::table) fn new_mut(index: &'a Index<K>, muts: Mut<'a>) -> Self {
Self {
index,
grid: TableView::Mut { muts, refs: Ref::default(), write: AHashSet::new() },
}
}
pub fn len_rows(&self) -> usize { self.index.keys().len() }
pub fn is_empty(&self) -> bool { self.index.keys().is_empty() }
pub fn len_cols(&self) -> usize { self.grid.len_cols() }
pub fn has_cols(&self) -> bool { self.grid.has_cols() }
pub fn contains<T: Data>(&self) -> bool { self.grid.contains::<T>() }
pub fn index(&self) -> &'a Index<K> { self.index }
pub fn contains_type(&self, id: &TypeId) -> bool { self.grid.contains_type(id) }
pub fn is_readable<T: Data>(&self) -> bool { self.grid.is_readable::<T>() }
pub fn is_writable<T: Data>(&self) -> bool { self.grid.is_writable::<T>() }
pub fn read<T: Data>(&mut self) -> Option<&'a [T]> { self.grid.read::<T>() }
pub fn write<T: Data>(&mut self) -> Option<&'a mut [T]> { self.grid.write::<T>() }
}
impl<'a, K> View<'a, K>
where
Key<K>: Hash + Eq,
{
pub fn contains_key(&self, key: &Key<K>) -> bool { self.index.keys().contains(key) }
pub(crate) fn index_of(&self, key: &Key<K>) -> Option<usize> {
self.index.keys().get_index_of(key)
}
}