use building_blocks_core::ExtentN;
use auto_impl::auto_impl;
#[auto_impl(&, &mut)]
pub trait Get<L> {
type Item;
fn get(&self, location: L) -> Self::Item;
}
#[auto_impl(&, &mut)]
pub trait GetRef<'a, L> {
type Item;
fn get_ref(&'a self, location: L) -> Self::Item;
}
#[auto_impl(&mut)]
pub trait GetMut<'a, L> {
type Item;
fn get_mut(&'a mut self, location: L) -> Self::Item;
}
#[auto_impl(&mut)]
pub trait GetMutPtr<L> {
type Item;
unsafe fn get_mut_ptr(&mut self, location: L) -> Self::Item;
}
macro_rules! impl_get_via_get_ref_and_clone {
($map:ty, $($type_params:ident),*) => {
impl<L, $($type_params),*> $crate::Get<L> for $map
where
Self: for<'r> $crate::GetRef<'r, L, Item = &'r T>,
T: Clone,
{
type Item = T;
#[inline]
fn get(&self, location: L) -> Self::Item {
self.get_ref(location).clone()
}
}
};
}
macro_rules! impl_get_for_tuple {
( $( $var:ident : $t:ident ),+ ) => {
impl<Coord, $($t),+> Get<Coord> for ($($t,)+)
where
Coord: Copy,
$($t: Get<Coord>),+
{
type Item = ($($t::Item,)+);
#[inline]
fn get(&self, offset: Coord) -> Self::Item {
let ($($var,)+) = self;
($($var.get(offset),)+)
}
}
impl<'a, Coord, $($t),+> GetRef<'a, Coord> for ($($t,)+)
where
Coord: Copy,
$($t: GetRef<'a, Coord>),+
{
type Item = ($($t::Item,)+);
#[inline]
fn get_ref(&'a self, offset: Coord) -> Self::Item {
let ($($var,)+) = self;
($($var.get_ref(offset),)+)
}
}
impl<'a, Coord, $($t),+> GetMut<'a, Coord> for ($($t,)+)
where
Coord: Copy,
$($t: GetMut<'a, Coord>),+
{
type Item = ($($t::Item,)+);
#[inline]
fn get_mut(&'a mut self, offset: Coord) -> Self::Item {
let ($($var,)+) = self;
($($var.get_mut(offset),)+)
}
}
impl<Coord, $($t),+> GetMutPtr<Coord> for ($($t,)+)
where
Coord: Copy,
$($t: GetMutPtr<Coord>),+
{
type Item = ($($t::Item,)+);
#[inline]
unsafe fn get_mut_ptr(&mut self, offset: Coord) -> Self::Item {
let ($($var,)+) = self;
($($var.get_mut_ptr(offset),)+)
}
}
}
}
impl_get_for_tuple! { a: A }
impl_get_for_tuple! { a: A, b: B }
impl_get_for_tuple! { a: A, b: B, c: C }
impl_get_for_tuple! { a: A, b: B, c: C, d: D }
impl_get_for_tuple! { a: A, b: B, c: C, d: D, e: E }
impl_get_for_tuple! { a: A, b: B, c: C, d: D, e: E, f: F }
#[auto_impl(&, &mut)]
pub trait ForEach<N, Coord> {
type Item;
fn for_each(&self, extent: &ExtentN<N>, f: impl FnMut(Coord, Self::Item));
}
#[doc(hidden)]
#[auto_impl(&mut)]
pub trait ForEachMutPtr<N, Coord> {
type Item;
unsafe fn for_each_mut_ptr(&mut self, extent: &ExtentN<N>, f: impl FnMut(Coord, Self::Item));
}
#[auto_impl(&mut)]
pub trait ForEachMut<'a, N, Coord> {
type Item;
fn for_each_mut(&'a mut self, extent: &ExtentN<N>, f: impl FnMut(Coord, Self::Item));
}
#[auto_impl(&mut)]
pub trait FillExtent<N> {
type Item;
fn fill_extent(&mut self, extent: &ExtentN<N>, value: Self::Item);
}
#[auto_impl(&, &mut)]
pub trait ReadExtent<'a, N> {
type Src;
type SrcIter: Iterator<Item = (ExtentN<N>, Self::Src)>;
fn read_extent(&'a self, extent: &ExtentN<N>) -> Self::SrcIter;
}
#[auto_impl(&mut)]
pub trait WriteExtent<N, Src> {
fn write_extent(&mut self, extent: &ExtentN<N>, src: Src);
}
pub fn copy_extent<'a, N, Src, Ms, Md>(extent: &ExtentN<N>, src_map: &'a Ms, dst_map: &mut Md)
where
Ms: ReadExtent<'a, N, Src = Src>,
Md: WriteExtent<N, Src>,
{
for (sub_extent, extent_src) in src_map.read_extent(extent) {
dst_map.write_extent(&sub_extent, extent_src);
}
}