use std::{iter::Iterator, marker::PhantomData};
use crate::{CellMap, Layer};
use super::{CellMapIter, Indexed, Layered};
#[derive(Clone)]
pub struct CellIter<'c, L: Layer, T: Clone> {
pub(crate) layer_limits: Option<Vec<L>>,
pub(crate) limits_idx: Option<usize>,
pub(crate) index: (usize, usize, usize),
pub(crate) map: &'c CellMap<L, T>,
}
pub struct CellIterMut<'c, L: Layer, T> {
pub(crate) layer_limits: Option<Vec<L>>,
pub(crate) limits_idx: Option<usize>,
pub(crate) index: (usize, usize, usize),
pub(crate) map: &'c mut CellMap<L, T>,
}
impl<'c, L: Layer, T: Clone> Iterator for CellIter<'c, L, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let l = self.index.0;
let y = self.index.1;
let x = self.index.2;
let data = if l < L::NUM_LAYERS
&& y < self.map.params.num_cells.y
&& x < self.map.params.num_cells.x
{
Some(self.map.data[l][(y, x)].clone())
} else {
return None;
};
self.index.2 += 1;
if self.index.2 >= self.map.params.num_cells.x {
self.index.2 = 0;
self.index.1 += 1;
}
if let Some(ref limits) = self.layer_limits {
if self.index.1 >= self.map.params.num_cells.y {
self.index.1 = 0;
let next_layer_lim_idx = self.limits_idx.unwrap() + 1;
if next_layer_lim_idx >= limits.len() {
self.index.0 = L::NUM_LAYERS;
} else {
self.index.0 = limits[next_layer_lim_idx].to_index();
*self.limits_idx.as_mut().unwrap() += 1;
}
}
}
else if self.index.1 >= self.map.params.num_cells.y {
self.index.1 = 0;
self.index.0 += 1;
}
data
}
}
impl<L, T> CellMapIter<L, T> for CellIter<'_, L, T>
where
L: Layer,
T: Clone,
{
fn limit_layers(&mut self, layers: &[L]) {
self.limits_idx = Some(layers[0].to_index());
self.layer_limits = Some(layers.into());
}
fn get_layer(&self) -> L {
L::from_index(self.index.0)
}
fn get_layer_checked(&self) -> Option<L> {
if self.index.0 < L::NUM_LAYERS {
Some(L::from_index(self.index.0))
} else {
None
}
}
fn get_x(&self) -> usize {
self.index.2.clone()
}
fn get_y(&self) -> usize {
self.index.1.clone()
}
}
impl<L, T> CellIter<'_, L, T>
where
L: Layer,
T: Clone,
{
pub fn layer(mut self, layer: L) -> Layered<L, T, Self> {
self.limit_layers(&[layer]);
Layered {
iter: self,
_phantom: PhantomData,
}
}
pub fn layers(mut self, layers: &[L]) -> Layered<L, T, Self> {
self.limit_layers(layers);
Layered {
iter: self,
_phantom: PhantomData,
}
}
pub fn indexed(self) -> Indexed<L, T, Self> {
Indexed {
iter: self,
_phantom: PhantomData,
}
}
}
impl<'c, L: Layer, T: Clone> Iterator for CellIterMut<'c, L, T> {
type Item = &'c mut T;
fn next(&mut self) -> Option<Self::Item> {
let l = self.index.0;
let y = self.index.1;
let x = self.index.2;
let data = if l < L::NUM_LAYERS
&& y < self.map.params.num_cells.y
&& x < self.map.params.num_cells.x
{
unsafe {
let layer_ptr = self.map.data.as_mut_ptr().add(l);
Some((&mut *layer_ptr).uget_mut((y, x)))
}
} else {
return None;
};
self.index.2 += 1;
if self.index.2 >= self.map.params.num_cells.x {
self.index.2 = 0;
self.index.1 += 1;
}
if let Some(ref limits) = self.layer_limits {
if self.index.1 >= self.map.params.num_cells.y {
self.index.1 = 0;
let next_layer_lim_idx = self.limits_idx.unwrap() + 1;
if next_layer_lim_idx >= limits.len() {
self.index.0 = L::NUM_LAYERS;
} else {
self.index.0 = limits[next_layer_lim_idx].to_index();
}
}
}
else if self.index.1 >= self.map.params.num_cells.y {
self.index.1 = 0;
self.index.0 += 1;
}
data
}
}
impl<L, T> CellMapIter<L, T> for CellIterMut<'_, L, T>
where
L: Layer,
T: Clone,
{
fn limit_layers(&mut self, layers: &[L]) {
self.limits_idx = Some(layers[0].to_index());
self.layer_limits = Some(layers.into());
}
fn get_layer(&self) -> L {
L::from_index(self.index.0)
}
fn get_layer_checked(&self) -> Option<L> {
if self.index.0 < L::NUM_LAYERS {
Some(L::from_index(self.index.0))
} else {
None
}
}
fn get_x(&self) -> usize {
self.index.2.clone()
}
fn get_y(&self) -> usize {
self.index.1.clone()
}
}
impl<L, T> CellIterMut<'_, L, T>
where
L: Layer,
T: Clone,
{
pub fn layer(mut self, layer: L) -> Layered<L, T, Self> {
self.limit_layers(&[layer]);
Layered {
iter: self,
_phantom: PhantomData,
}
}
pub fn layers(mut self, layers: &[L]) -> Layered<L, T, Self> {
self.limit_layers(layers);
Layered {
iter: self,
_phantom: PhantomData,
}
}
pub fn indexed(self) -> Indexed<L, T, Self> {
Indexed {
iter: self,
_phantom: PhantomData,
}
}
}
#[cfg(test)]
mod tests {
use nalgebra::Vector2;
use crate::{CellMap, CellMapParams, Layer};
#[derive(Clone, Copy)]
#[allow(dead_code)]
enum MyLayers {
Layer0,
Layer1,
Layer2,
}
impl Layer for MyLayers {
const NUM_LAYERS: usize = 3;
const FIRST: Self = Self::Layer0;
fn to_index(&self) -> usize {
match self {
Self::Layer0 => 0,
Self::Layer1 => 1,
Self::Layer2 => 2,
}
}
fn from_index(index: usize) -> Self {
match index {
0 => Self::Layer0,
1 => Self::Layer1,
2 => Self::Layer2,
_ => panic!(
"Got a layer index of {} but there are only {} layers",
index,
Self::NUM_LAYERS
),
}
}
}
#[test]
fn iter() {
let map = CellMap::<MyLayers, f64>::new_from_elem(
CellMapParams {
cell_size: Vector2::new(1.0, 1.0),
num_cells: Vector2::new(5, 5),
centre: Vector2::new(0.0, 0.0),
},
1.0,
);
let map_iter = map.iter();
assert_eq!(
map_iter.clone().count(),
map.num_cells().x * map.num_cells().y * MyLayers::NUM_LAYERS
);
assert!(map_iter.clone().all(|v| v == 1.0));
}
#[test]
fn iter_mut() {
let mut map = CellMap::<MyLayers, f64>::new_from_elem(
CellMapParams {
cell_size: Vector2::new(1.0, 1.0),
num_cells: Vector2::new(5, 5),
centre: Vector2::new(0.0, 0.0),
},
1.0,
);
assert_eq!(
map.iter_mut().count(),
map.num_cells().x * map.num_cells().y * MyLayers::NUM_LAYERS
);
assert!(map.iter().all(|v| v == 1.0));
map.iter_mut().for_each(|v| *v = 2.0);
assert!(map.iter().all(|v| v == 2.0));
}
}