use crate::{
Array, Channel, Chunk, ChunkHashMap, ChunkKey, ChunkMap, ChunkReadStorage, ChunkWriteStorage,
FillChannels, SmallKeyHashMap,
};
use building_blocks_core::{ExtentN, IntegerPoint, PointN};
use core::hash::Hash;
pub trait ChunkMapBuilder<N, T>: Sized {
type Chunk: Chunk;
fn chunk_shape(&self) -> PointN<N>;
fn ambient_value(&self) -> T;
fn new_ambient(&self, extent: ExtentN<N>) -> Self::Chunk;
fn build_with_rw_storage<Store>(self, storage: Store) -> ChunkMap<N, T, Self, Store>
where
PointN<N>: IntegerPoint<N>,
Store: ChunkReadStorage<N, Self::Chunk> + ChunkWriteStorage<N, Self::Chunk>,
{
ChunkMap::new(self, storage)
}
fn build_with_read_storage<Store>(self, storage: Store) -> ChunkMap<N, T, Self, Store>
where
PointN<N>: IntegerPoint<N>,
Store: ChunkReadStorage<N, Self::Chunk>,
{
ChunkMap::new(self, storage)
}
fn build_with_write_storage<Store>(self, storage: Store) -> ChunkMap<N, T, Self, Store>
where
PointN<N>: IntegerPoint<N>,
Store: ChunkWriteStorage<N, Self::Chunk>,
{
ChunkMap::new(self, storage)
}
fn build_with_hash_map_storage(self) -> ChunkHashMap<N, T, Self>
where
PointN<N>: IntegerPoint<N>,
ChunkKey<N>: Eq + Hash,
{
Self::build_with_rw_storage(self, SmallKeyHashMap::default())
}
}
#[derive(Clone, Copy)]
pub struct ChunkMapBuilderNxM<N, T, Chan> {
pub chunk_shape: PointN<N>,
pub ambient_value: T,
marker: std::marker::PhantomData<Chan>,
}
impl<N, T, Chan> ChunkMapBuilderNxM<N, T, Chan> {
pub const fn new(chunk_shape: PointN<N>, ambient_value: T) -> Self {
Self {
chunk_shape,
ambient_value,
marker: std::marker::PhantomData,
}
}
}
macro_rules! builder_type_alias {
($name:ident, $dim:ty, $( $chan:ident ),+ ) => {
pub type $name<$( $chan ),+> = ChunkMapBuilderNxM<$dim, ($($chan),+), ($(Channel<$chan>),+)>;
};
}
pub mod multichannel_aliases {
use super::*;
pub type ChunkMapBuilderNx1<N, A> = ChunkMapBuilderNxM<N, A, Channel<A>>;
pub type ChunkMapBuilder2x1<A> = ChunkMapBuilderNxM<[i32; 2], A, Channel<A>>;
builder_type_alias!(ChunkMapBuilder2x2, [i32; 2], A, B);
builder_type_alias!(ChunkMapBuilder2x3, [i32; 2], A, B, C);
builder_type_alias!(ChunkMapBuilder2x4, [i32; 2], A, B, C, D);
builder_type_alias!(ChunkMapBuilder2x5, [i32; 2], A, B, C, D, E);
builder_type_alias!(ChunkMapBuilder2x6, [i32; 2], A, B, C, D, E, F);
pub type ChunkMapBuilder3x1<A> = ChunkMapBuilderNxM<[i32; 3], A, Channel<A>>;
builder_type_alias!(ChunkMapBuilder3x2, [i32; 3], A, B);
builder_type_alias!(ChunkMapBuilder3x3, [i32; 3], A, B, C);
builder_type_alias!(ChunkMapBuilder3x4, [i32; 3], A, B, C, D);
builder_type_alias!(ChunkMapBuilder3x5, [i32; 3], A, B, C, D, E);
builder_type_alias!(ChunkMapBuilder3x6, [i32; 3], A, B, C, D, E, F);
}
pub use multichannel_aliases::*;
impl<N, T, Chan> ChunkMapBuilder<N, T> for ChunkMapBuilderNxM<N, T, Chan>
where
PointN<N>: IntegerPoint<N>,
T: Clone,
Chan: FillChannels<Data = T>,
{
type Chunk = Array<N, Chan>;
fn chunk_shape(&self) -> PointN<N> {
self.chunk_shape
}
fn ambient_value(&self) -> T {
self.ambient_value.clone()
}
fn new_ambient(&self, extent: ExtentN<N>) -> Self::Chunk {
Array::fill(extent, self.ambient_value())
}
}