use {
crate::{
copy_map::StaticCopyMap,
map::iters::{IntoIter, IntoValues, Iter, IterMut},
storage::Storage,
variants::Variants,
Linearize, LinearizeExt, Linearized,
},
core::{
array::TryFromSliceError,
borrow::{Borrow, BorrowMut},
cmp::Ordering,
fmt::{Debug, Formatter},
hash::{Hash, Hasher},
mem,
ops::{Deref, DerefMut, Index, IndexMut},
},
};
pub(crate) mod iters;
#[repr(transparent)]
pub struct StaticMap<L, T>(
pub <L as Linearize>::Storage<T>,
)
where
L: Linearize + ?Sized;
impl<L, T> StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
pub fn from_fn(mut cb: impl FnMut(L) -> T) -> Self
where
L: Sized,
{
Self(<L::Storage<T> as Storage<L, T>>::from_fn(|i| unsafe {
cb(L::from_linear_unchecked(i))
}))
}
#[inline]
pub const fn from_ref(storage: &<L as Linearize>::Storage<T>) -> &Self {
unsafe {
mem::transmute(storage)
}
}
#[inline]
pub fn from_mut(storage: &mut <L as Linearize>::Storage<T>) -> &mut Self {
unsafe {
mem::transmute(storage)
}
}
#[inline]
pub fn try_from_iter(
iter: impl IntoIterator<Item = (L, T)>,
) -> Result<Self, StaticMap<L, Option<T>>>
where
L: Sized,
{
let mut res = StaticMap::<L, Option<T>>::default();
for (k, v) in iter {
res[k] = Some(v);
}
if res.values().any(|v| v.is_none()) {
return Err(res);
}
Ok(res.map_values(|v| v.unwrap()))
}
#[inline]
pub fn into_copy(self) -> StaticCopyMap<L, T>
where
T: Copy,
{
StaticCopyMap(self.0.into_copy())
}
#[inline]
pub fn from_copy(map: StaticCopyMap<L, T>) -> Self
where
T: Copy,
{
map.into_static_map()
}
#[inline]
pub fn as_copy(&self) -> &StaticCopyMap<L, T>
where
T: Copy,
{
StaticCopyMap::from_ref(self.0.as_copy())
}
#[inline]
pub fn as_copy_mut(&mut self) -> &mut StaticCopyMap<L, T>
where
T: Copy,
{
StaticCopyMap::from_mut(self.0.as_copy_mut())
}
#[inline]
pub fn each_ref(&self) -> StaticCopyMap<L, &T> {
StaticCopyMap(self.0.each_ref().into_copy())
}
#[inline]
pub fn each_mut(&mut self) -> StaticMap<L, &mut T> {
StaticMap(self.0.each_mut())
}
#[inline]
pub fn map<U>(self, mut map: impl FnMut(L, T) -> U) -> StaticMap<L, U>
where
L: Sized,
{
StaticMap(self.0.map(|i, t| {
let l = unsafe {
L::from_linear_unchecked(i)
};
map(l, t)
}))
}
#[inline]
pub fn map_values<U>(self, mut map: impl FnMut(T) -> U) -> StaticMap<L, U> {
StaticMap(self.0.map(|_, t| map(t)))
}
#[inline]
pub fn clear(&mut self)
where
T: Default,
{
for v in self.0.as_mut() {
*v = Default::default();
}
}
#[inline]
pub fn keys(&self) -> Variants<L>
where
L: Sized,
{
L::variants()
}
#[inline]
pub fn values(&self) -> core::slice::Iter<'_, T> {
self.as_ref().iter()
}
#[inline]
pub fn values_mut(&mut self) -> core::slice::IterMut<'_, T> {
self.as_mut().iter_mut()
}
#[inline]
pub fn iter(&self) -> Iter<'_, L, T>
where
L: Sized,
{
Iter::new(&self.0)
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, L, T>
where
L: Sized,
{
IterMut::new(&mut self.0)
}
pub fn into_values(self) -> IntoValues<L, T>
where
L: Sized,
{
IntoValues::new(self.0)
}
}
impl<L, T> Deref for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
type Target = [T];
#[inline]
fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}
impl<L, T> DerefMut for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.as_mut()
}
}
impl<L, T> FromIterator<(L, T)> for StaticMap<L, T>
where
L: Linearize,
T: Default,
{
#[inline]
fn from_iter<I: IntoIterator<Item = (L, T)>>(iter: I) -> Self {
let mut res = StaticMap::<L, Option<T>>::default();
for (k, v) in iter {
res[k] = Some(v);
}
res.map_values(|v| v.unwrap_or_default())
}
}
impl<'a, L, T> FromIterator<(&'a L, T)> for StaticMap<L, T>
where
L: Linearize,
T: Default,
{
#[inline]
fn from_iter<I: IntoIterator<Item = (&'a L, T)>>(iter: I) -> Self {
let mut res = StaticMap::<L, Option<T>>::default();
for (k, v) in iter {
res[k] = Some(v);
}
res.map_values(|v| v.unwrap_or_default())
}
}
impl<L, T> Clone for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self(<L::Storage<T> as Storage<L, T>>::clone(&self.0))
}
#[inline]
fn clone_from(&mut self, source: &Self) {
<L::Storage<T> as Storage<L, T>>::clone_from(&mut self.0, &source.0);
}
}
impl<L, T> Index<&'_ L> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
type Output = T;
#[inline]
fn index(&self, index: &L) -> &Self::Output {
self.index(index.linearized())
}
}
impl<L, T> Index<L> for StaticMap<L, T>
where
L: Linearize,
{
type Output = T;
#[inline]
fn index(&self, index: L) -> &Self::Output {
self.index(index.linearized())
}
}
impl<L, T> Index<Linearized<L>> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
type Output = T;
#[inline(always)]
fn index(&self, index: Linearized<L>) -> &Self::Output {
unsafe {
<L::Storage<T> as AsRef<[T]>>::as_ref(&self.0).get_unchecked(index.get())
}
}
}
impl<L, T> IndexMut<&'_ L> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
fn index_mut(&mut self, index: &L) -> &mut Self::Output {
self.index_mut(index.linearized())
}
}
impl<L, T> IndexMut<L> for StaticMap<L, T>
where
L: Linearize,
{
#[inline]
fn index_mut(&mut self, index: L) -> &mut Self::Output {
self.index_mut(index.linearized())
}
}
impl<L, T> IndexMut<Linearized<L>> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline(always)]
fn index_mut(&mut self, index: Linearized<L>) -> &mut Self::Output {
unsafe {
<L::Storage<T> as AsMut<[T]>>::as_mut(&mut self.0).get_unchecked_mut(index.get())
}
}
}
impl<L, T> AsMut<[T]> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self.0.as_mut()
}
}
impl<L, T> AsRef<[T]> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
fn as_ref(&self) -> &[T] {
self.0.as_ref()
}
}
impl<L, T> Borrow<[T]> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
fn borrow(&self) -> &[T] {
self.0.borrow()
}
}
impl<L, T> BorrowMut<[T]> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
#[inline]
fn borrow_mut(&mut self) -> &mut [T] {
self.0.borrow_mut()
}
}
impl<L, T> Debug for StaticMap<L, T>
where
L: Linearize,
L: Debug,
T: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let mut map = f.debug_map();
for (k, v) in self {
map.key(&k).value(v);
}
map.finish()
}
}
impl<L, T> Default for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Default,
{
#[inline]
fn default() -> Self {
Self(Storage::default())
}
}
impl<L, T> Eq for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Eq,
{
}
impl<L, T> Hash for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Hash,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.as_hash().hash(state)
}
}
impl<L, T> Ord for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Ord,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
#[inline]
fn max(self, other: Self) -> Self
where
Self: Sized,
{
Self(self.0.max(other.0))
}
#[inline]
fn min(self, other: Self) -> Self
where
Self: Sized,
{
Self(self.0.min(other.0))
}
#[inline]
fn clamp(self, min: Self, max: Self) -> Self
where
Self: Sized,
Self: PartialOrd,
{
Self(self.0.clamp(min.0, max.0))
}
}
impl<L, T> PartialEq for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl<L, T> PartialOrd for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<'a, L, T> TryFrom<&'a [T]> for &'a StaticMap<L, T>
where
L: Linearize + ?Sized,
{
type Error = TryFromSliceError;
#[inline]
fn try_from(value: &'a [T]) -> Result<Self, Self::Error> {
<L::Storage<T>>::ref_try_from(value).map(StaticMap::from_ref)
}
}
impl<'a, L, T> TryFrom<&'a mut [T]> for &'a mut StaticMap<L, T>
where
L: Linearize + ?Sized,
T:,
{
type Error = TryFromSliceError;
#[inline]
fn try_from(value: &'a mut [T]) -> Result<Self, Self::Error> {
<L::Storage<T>>::mut_try_from(value).map(StaticMap::from_mut)
}
}
impl<L, T> TryFrom<&[T]> for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Copy,
{
type Error = TryFromSliceError;
#[inline]
fn try_from(value: &[T]) -> Result<Self, Self::Error> {
<L::Storage<T>>::copy_ref_try_from(value).map(Self)
}
}
impl<L, T> TryFrom<&mut [T]> for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Copy,
{
type Error = TryFromSliceError;
#[inline]
fn try_from(value: &mut [T]) -> Result<Self, Self::Error> {
<L::Storage<T>>::copy_mut_try_from(value).map(Self)
}
}
#[cfg(feature = "std")]
impl<L, T> TryFrom<Vec<T>> for StaticMap<L, T>
where
L: Linearize + ?Sized,
{
type Error = Vec<T>;
#[inline]
fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
<L::Storage<T>>::vec_try_from(value).map(Self)
}
}
impl<L, T> Extend<(L, T)> for StaticMap<L, T>
where
L: Linearize,
{
#[inline]
fn extend<I: IntoIterator<Item = (L, T)>>(&mut self, iter: I) {
for (k, v) in iter {
self[k] = v;
}
}
}
impl<'a, L, T> Extend<(&'a L, &'a T)> for StaticMap<L, T>
where
L: Linearize + ?Sized,
T: Clone,
{
#[inline]
fn extend<I: IntoIterator<Item = (&'a L, &'a T)>>(&mut self, iter: I) {
for (k, v) in iter {
self[k] = v.clone();
}
}
}
impl<'a, L, T> IntoIterator for &'a StaticMap<L, T>
where
L: Linearize,
T: 'a,
{
type Item = (L, &'a T);
type IntoIter = Iter<'a, L, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, L, T> IntoIterator for &'a mut StaticMap<L, T>
where
L: Linearize,
{
type Item = (L, &'a mut T);
type IntoIter = IterMut<'a, L, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<L, T> IntoIterator for StaticMap<L, T>
where
L: Linearize,
{
type Item = (L, T);
type IntoIter = IntoIter<L, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self.0.into_storage())
}
}
impl<L, T> From<StaticCopyMap<L, T>> for StaticMap<L, T>
where
L: Linearize,
T: Copy,
{
fn from(value: StaticCopyMap<L, T>) -> Self {
value.into_static_map()
}
}
impl<L, T> AsRef<StaticCopyMap<L, T>> for StaticMap<L, T>
where
L: Linearize,
T: Copy,
{
fn as_ref(&self) -> &StaticCopyMap<L, T> {
self.as_copy()
}
}
impl<L, T> AsMut<StaticCopyMap<L, T>> for StaticMap<L, T>
where
L: Linearize,
T: Copy,
{
fn as_mut(&mut self) -> &mut StaticCopyMap<L, T> {
self.as_copy_mut()
}
}
impl<L, T> Borrow<StaticCopyMap<L, T>> for StaticMap<L, T>
where
L: Linearize,
T: Copy,
{
fn borrow(&self) -> &StaticCopyMap<L, T> {
self.as_copy()
}
}
impl<L, T> BorrowMut<StaticCopyMap<L, T>> for StaticMap<L, T>
where
L: Linearize,
T: Copy,
{
fn borrow_mut(&mut self) -> &mut StaticCopyMap<L, T> {
self.as_copy_mut()
}
}