use core::{
ops::{Range, Index},
iter::FusedIterator
};
use super::{
Tile,
Field
};
#[derive(Clone)]
pub struct RowIter<'f> {
field: &'f Field,
row: usize,
index: Range<usize>
}
impl<'f> RowIter<'f> {
#[inline(always)]
pub fn new(field: &'f Field, row: usize) -> Self {
assert!(row < field.dimensions()[1].get());
Self {field, row, index: 0..field.dimensions()[0].get()}
}
#[inline(always)]
pub fn get(&self, column: usize) -> Option<Tile> {
self.field.get([column, self.row]).copied()
}
#[inline(always)]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn column(&self, column: usize) -> Tile {
self.get(column).expect("index out of bounds")
}
#[inline(always)]
pub fn field(&self) -> &'f Field {
self.field
}
}
impl<'f> Iterator for RowIter<'f> {
type Item = Tile;
fn next(&mut self) -> Option<Self::Item> {
if self.index.end - self.index.start == 0 {
return None;
}
let el = self.field.get([self.index.start, self.row]);
self.index.start += 1;
el.copied()
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'f> DoubleEndedIterator for RowIter<'f> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.index.end - self.index.start == 0 {
return None;
}
self.index.end -= 1;
self.field.get([self.index.end, self.row]).copied()
}
}
impl<'f> ExactSizeIterator for RowIter<'f> {
#[inline(always)]
fn len(&self) -> usize {
self.index.end - self.index.start
}
}
impl FusedIterator for RowIter<'_> {}
impl Index<usize> for RowIter<'_> {
type Output = Tile;
#[inline(always)]
fn index(&self, column: usize) -> &Tile {
self.field.get([column, self.row]).expect("index out of bounds")
}
}
#[derive(Clone)]
pub struct ColumnIter<'f> {
field: &'f Field,
column: usize,
index: Range<usize>
}
impl<'f> ColumnIter<'f> {
#[inline(always)]
pub fn new(field: &'f Field, column: usize) -> Self {
assert!(column < field.dimensions()[0].get());
Self {field, column, index: 0..field.dimensions()[0].get()}
}
#[inline(always)]
pub fn get(&self, row: usize) -> Option<Tile> {
self.field.get([self.column, row]).copied()
}
#[inline(always)]
#[cfg_attr(feature = "track_caller", track_caller)]
pub fn row(&self, row: usize) -> Tile {
self.get(row).expect("index out of bounds")
}
#[inline(always)]
pub fn field(&self) -> &'f Field {
self.field
}
}
impl<'f> Iterator for ColumnIter<'f> {
type Item = Tile;
fn next(&mut self) -> Option<Self::Item> {
if self.len() == 0 {
return None;
}
let el = self.field.get([self.column, self.index.start]);
self.index.start += 1;
el.copied()
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'f> DoubleEndedIterator for ColumnIter<'f> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.len() == 0 {
return None;
}
self.index.end -= 1;
self.field.get([self.column, self.index.end]).copied()
}
}
impl<'f> ExactSizeIterator for ColumnIter<'f> {
#[inline(always)]
fn len(&self) -> usize {
self.index.end - self.index.start
}
}
impl FusedIterator for ColumnIter<'_> {}
impl Index<usize> for ColumnIter<'_> {
type Output = Tile;
#[inline(always)]
fn index(&self, row: usize) -> &Tile {
self.field.get([self.column, row]).expect("index out of bounds")
}
}
#[derive(Clone)]
pub struct FieldRowsIter<'f> {
field: &'f Field,
index: Range<usize>
}
impl<'f> FieldRowsIter<'f> {
#[inline(always)]
pub fn new(field: &'f Field) -> Self {
Self {
field, index: 0..field.dimensions()[1].get()
}
}
}
impl<'f> Iterator for FieldRowsIter<'f> {
type Item = RowIter<'f>;
fn next(&mut self) -> Option<Self::Item> {
if self.len() == 0 {
return None;
}
let el = Some(self.field.row(self.index.start));
self.index.start += 1;
el
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'f> DoubleEndedIterator for FieldRowsIter<'f> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.len() == 0 {
return None;
}
self.index.end -= 1;
Some(self.field.row(self.index.end))
}
}
impl<'f> ExactSizeIterator for FieldRowsIter<'f> {
#[inline(always)]
fn len(&self) -> usize {
self.index.end - self.index.start
}
}
impl FusedIterator for FieldRowsIter<'_> {}
#[derive(Clone)]
pub struct FieldColumnsIter<'f> {
field: &'f Field,
index: Range<usize>
}
impl<'f> FieldColumnsIter<'f> {
#[inline(always)]
pub fn new(field: &'f Field) -> Self {
Self {
field, index: 0..field.dimensions()[0].get()
}
}
}
impl<'f> Iterator for FieldColumnsIter<'f> {
type Item = ColumnIter<'f>;
fn next(&mut self) -> Option<Self::Item> {
if self.len() == 0 {
return None;
}
let el = Some(self.field.column(self.index.start));
self.index.start += 1;
el
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'f> DoubleEndedIterator for FieldColumnsIter<'f> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.len() == 0 {
return None;
}
self.index.end -= 1;
Some(self.field.column(self.index.end))
}
}
impl<'f> ExactSizeIterator for FieldColumnsIter<'f> {
#[inline(always)]
fn len(&self) -> usize {
self.index.end - self.index.start
}
}
impl FusedIterator for FieldColumnsIter<'_> {}