hashgrid 0.1.0

A 2D spatial-hash grid library
Documentation
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 {
        // assert!(vec.iter().all(|(id, _)| *id != key));
        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])
    }
}