use crate::MapKey;
use core::{
cmp::Ordering,
fmt, hash, iter,
ops::{Index, IndexMut},
};
use count_enum::{iter_each, Enum, IterEachFrom};
pub struct TotalMap<K: MapKey, V>(K::MapTy<V>);
impl<K: MapKey, V> TotalMap<K, V> {
pub fn new(v: V) -> Self
where
V: Clone,
{
Self::from_fn(|_| v.clone())
}
pub fn from_fn(f: impl FnMut(K) -> V) -> Self {
Self(K::k_from_fn(f))
}
pub fn as_ref(&self) -> TotalMap<K, &V> {
TotalMap(K::k_as_ref(&self.0))
}
pub fn as_mut(&mut self) -> TotalMap<K, &mut V> {
TotalMap(K::k_as_mut(&mut self.0))
}
pub fn map<W>(self, f: impl FnMut(V) -> W) -> TotalMap<K, W> {
TotalMap(K::k_map(self.0, f))
}
pub fn map_with_key<W>(self, f: impl FnMut(K, V) -> W) -> TotalMap<K, W> {
TotalMap(K::k_map_with_key(self.0, f))
}
pub fn map_ref<W>(&self, f: impl FnMut(&V) -> W) -> TotalMap<K, W> {
TotalMap(K::k_map(self.as_ref().0, f))
}
pub fn zip<W>(self, that: TotalMap<K, W>) -> TotalMap<K, (V, W)> {
self.zip_with(that, |a, b| (a, b))
}
pub fn zip_with<V2, W>(
self,
that: TotalMap<K, V2>,
f: impl FnMut(V, V2) -> W,
) -> TotalMap<K, W> {
TotalMap(K::k_zip_with(self.0, that.0, f))
}
pub fn into_values(self) -> K::Values<V> {
K::k_into_values(self.0)
}
pub fn values(&self) -> K::Values<&V> {
K::k_into_values(self.as_ref().0)
}
pub fn values_mut(&mut self) -> K::Values<&mut V> {
K::k_into_values(self.as_mut().0)
}
}
impl<K: MapKey + Enum, V> TotalMap<K, V> {
pub const LEN: Option<usize> = K::CARD;
pub fn iter(&self) -> iter::Zip<IterEachFrom<K>, K::Values<&V>> {
iter_each().zip(self.values())
}
pub fn iter_mut(&mut self) -> iter::Zip<IterEachFrom<K>, K::Values<&mut V>> {
iter_each().zip(self.values_mut())
}
}
impl<K: MapKey, V> Index<&K> for TotalMap<K, V> {
type Output = V;
fn index(&self, index: &K) -> &Self::Output {
K::k_index(&self.0, index)
}
}
impl<K: MapKey, V> IndexMut<&K> for TotalMap<K, V> {
fn index_mut(&mut self, index: &K) -> &mut Self::Output {
K::k_index_mut(&mut self.0, index)
}
}
impl<K: MapKey, V: Clone> Clone for TotalMap<K, V> {
fn clone(&self) -> Self {
self.map_ref(V::clone)
}
}
impl<K: MapKey, V: Default> Default for TotalMap<K, V> {
fn default() -> Self {
Self::from_fn(|_| V::default())
}
}
impl<K: MapKey, V: PartialEq> PartialEq for TotalMap<K, V> {
fn eq(&self, other: &Self) -> bool {
self.values().eq(other.values())
}
}
impl<K: MapKey, V: Eq> Eq for TotalMap<K, V> {}
impl<K: MapKey, V: PartialOrd> PartialOrd for TotalMap<K, V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.values().partial_cmp(other.values())
}
}
impl<K: MapKey, V: Ord> Ord for TotalMap<K, V> {
fn cmp(&self, other: &Self) -> Ordering {
self.values().cmp(other.values())
}
}
impl<K: MapKey, V: hash::Hash> hash::Hash for TotalMap<K, V> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.values().for_each(|v| v.hash(state));
}
}
impl<K: MapKey + Enum + fmt::Debug, V: fmt::Debug> fmt::Debug for TotalMap<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<'a, K: MapKey, V> Extend<(&'a K, V)> for TotalMap<K, V> {
fn extend<T: IntoIterator<Item = (&'a K, V)>>(&mut self, iter: T) {
iter.into_iter().for_each(|(k, v)| self[k] = v);
}
}
impl<'a, K: MapKey, V: Default> FromIterator<(&'a K, V)> for TotalMap<K, V> {
fn from_iter<T: IntoIterator<Item = (&'a K, V)>>(iter: T) -> Self {
let mut this = Self::default();
this.extend(iter);
this
}
}
impl<K: MapKey + Enum, V> IntoIterator for TotalMap<K, V> {
type Item = (K, V);
type IntoIter = iter::Zip<IterEachFrom<K>, K::Values<V>>;
fn into_iter(self) -> Self::IntoIter {
iter_each().zip(self.into_values())
}
}
impl<'a, K: MapKey + Enum, V> IntoIterator for &'a TotalMap<K, V> {
type Item = (K, &'a V);
type IntoIter = iter::Zip<IterEachFrom<K>, K::Values<&'a V>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K: MapKey + Enum, V> IntoIterator for &'a mut TotalMap<K, V> {
type Item = (K, &'a mut V);
type IntoIter = iter::Zip<IterEachFrom<K>, K::Values<&'a mut V>>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}