use std::ops::{Add, RangeBounds, Sub};
use crate::{
grid::config::Entity,
grid::records::{ExactRecords, Records},
settings::object::{cell::EntityOnce, Object},
};
use super::util::bounds_to_usize;
#[derive(Debug)]
pub struct Rows<R> {
range: R,
}
impl<R> Rows<R> {
pub fn new(range: R) -> Self
where
R: RangeBounds<usize>,
{
Self { range }
}
pub(crate) const fn get_range(&self) -> &R {
&self.range
}
}
impl Rows<()> {
pub const fn one(index: usize) -> Row {
Row { index }
}
pub const fn first() -> FirstRow {
FirstRow
}
pub const fn last() -> LastRow {
LastRow
}
}
impl<I, R> Object<I> for Rows<R>
where
R: RangeBounds<usize>,
I: ExactRecords,
{
type Iter = RowsIter;
fn cells(&self, records: &I) -> Self::Iter {
let start = self.range.start_bound();
let end = self.range.end_bound();
let max = records.count_rows();
let (x, y) = bounds_to_usize(start, end, max);
RowsIter::new(x, y)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Row {
index: usize,
}
impl<I> Object<I> for Row {
type Iter = EntityOnce;
fn cells(&self, _: &I) -> Self::Iter {
EntityOnce::new(Some(Entity::Row(self.index)))
}
}
impl From<Row> for usize {
fn from(val: Row) -> Self {
val.index
}
}
impl From<usize> for Row {
fn from(index: usize) -> Row {
Row { index }
}
}
#[derive(Debug)]
pub struct FirstRow;
impl<I> Object<I> for FirstRow
where
I: Records + ExactRecords,
{
type Iter = EntityOnce;
fn cells(&self, records: &I) -> Self::Iter {
if records.count_columns() == 0 || records.count_rows() == 0 {
return EntityOnce::new(None);
}
EntityOnce::new(Some(Entity::Row(0)))
}
}
impl Add<usize> for FirstRow {
type Output = Row;
fn add(self, rhs: usize) -> Self::Output {
Row { index: rhs }
}
}
#[derive(Debug)]
pub struct LastRow;
impl<I> Object<I> for LastRow
where
I: Records + ExactRecords,
{
type Iter = EntityOnce;
fn cells(&self, records: &I) -> Self::Iter {
let count_rows = records.count_rows();
if records.count_columns() == 0 || count_rows == 0 {
return EntityOnce::new(None);
}
let row = count_rows - 1;
EntityOnce::new(Some(Entity::Row(row)))
}
}
impl Sub<usize> for LastRow {
type Output = LastRowOffset;
fn sub(self, rhs: usize) -> Self::Output {
LastRowOffset::sub(rhs)
}
}
impl Add<usize> for LastRow {
type Output = LastRowOffset;
fn add(self, rhs: usize) -> Self::Output {
LastRowOffset::add(rhs)
}
}
#[derive(Debug)]
pub struct LastRowOffset {
offset: usize,
sign: bool,
}
impl LastRowOffset {
fn sub(offset: usize) -> Self {
Self {
offset,
sign: false,
}
}
fn add(offset: usize) -> Self {
Self { offset, sign: true }
}
}
impl<I> Object<I> for LastRowOffset
where
I: Records + ExactRecords,
{
type Iter = EntityOnce;
fn cells(&self, records: &I) -> Self::Iter {
let count_rows = records.count_rows();
if records.count_columns() == 0 || count_rows == 0 {
return EntityOnce::new(None);
}
let last_row = count_rows - 1;
if self.sign {
let row = last_row + self.offset;
EntityOnce::new(Some(Entity::Row(row)))
} else {
if self.offset > last_row {
return EntityOnce::new(None);
}
let row = last_row - self.offset;
EntityOnce::new(Some(Entity::Row(row)))
}
}
}
#[derive(Debug)]
pub struct RowsIter {
start: usize,
end: usize,
}
impl RowsIter {
const fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
}
impl Iterator for RowsIter {
type Item = Entity;
fn next(&mut self) -> Option<Self::Item> {
if self.start >= self.end {
return None;
}
let col = self.start;
self.start += 1;
Some(Entity::Row(col))
}
}