use std::{marker::PhantomData, ops::RangeInclusive};
use smallvec::{Array, SmallVec};
use crate::{IntoCellIter, range::Range};
pub trait Mapper<T, A> {
type Entry;
type Input;
type Output: IntoCellIter<A>;
fn insert(
vec: &mut SmallVec<impl Array<Item = Self::Entry>>,
key: T,
entity: Self::Input,
) -> Self::Output;
fn remove(vec: &mut SmallVec<impl Array<Item = Self::Entry>>, key: &T) -> Option<Self::Output>;
}
pub struct RangeMapper<T, A>(PhantomData<(T, A)>);
impl<T: Copy + Eq, A: Copy + Eq> Mapper<T, A> for RangeMapper<T, A>
where
RangeInclusive<A>: Iterator<Item = A>,
{
type Entry = (T, Range<A>);
type Input = Range<A>;
type Output = Range<A>;
#[inline(always)]
fn insert(
vec: &mut SmallVec<impl Array<Item = Self::Entry>>,
key: T,
range: Self::Input,
) -> Self::Output {
vec.push((key, range));
range
}
#[inline(always)]
fn remove(vec: &mut SmallVec<impl Array<Item = Self::Entry>>, key: &T) -> Option<Self::Output> {
let i = vec.iter().position(|(id, _)| id == key)?;
let (_, range) = vec.swap_remove(i);
Some(range)
}
}
pub struct RangeOneMapper<T, A>(PhantomData<(T, A)>);
impl<T: Copy + Eq, A: Copy + Eq> Mapper<T, A> for RangeOneMapper<T, A>
where
RangeInclusive<A>: Iterator<Item = A>,
{
type Entry = (T, [A; 2]);
type Input = Range<A>;
type Output = Range<A>;
#[inline(always)]
fn insert(
vec: &mut SmallVec<impl Array<Item = Self::Entry>>,
key: T,
range: Self::Input,
) -> Self::Output {
vec.push((key, range.min));
if range.min != range.max {
vec.push((key, range.max));
}
range
}
#[inline(always)]
fn remove(vec: &mut SmallVec<impl Array<Item = Self::Entry>>, key: &T) -> Option<Self::Output> {
let i = vec.iter().position(|(id, _)| id == key)?;
let (_, min) = vec.remove(i);
let max = if let Some((id, _)) = vec.get(i)
&& id == key
{
let (_, max) = vec.remove(i);
max
} else {
min
};
Some(Range::new(min, max))
}
}
pub struct OneMapper<T, A>(PhantomData<(T, A)>);
impl<T: Copy + Eq, A: Copy + Eq> Mapper<T, A> for OneMapper<T, A>
where
RangeInclusive<A>: Iterator<Item = A>,
{
type Entry = (T, [A; 2]);
type Input = [A; 2];
type Output = [[A; 2]; 1];
#[inline(always)]
fn insert(
vec: &mut SmallVec<impl Array<Item = Self::Entry>>,
key: T,
entity: Self::Input,
) -> Self::Output {
vec.push((key, entity));
[entity]
}
#[inline(always)]
fn remove(vec: &mut SmallVec<impl Array<Item = Self::Entry>>, key: &T) -> Option<Self::Output> {
let i = vec.iter().position(|(id, _)| id == key)?;
let (_, entity) = vec.swap_remove(i);
Some([entity])
}
}