blob: bcbe2acf5ed01ea2004478f2a28fd8124f90ed6b [file] [log] [blame]
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;
/// Column denotes a set of cells on given columns on a [`Table`].
///
/// [`Table`]: crate::Table
#[derive(Debug)]
pub struct Columns<R> {
range: R,
}
impl<R> Columns<R> {
/// Returns a new instance of [`Columns`] for a range of columns.
///
/// If the boundaries are exceeded it may panic.
pub fn new(range: R) -> Self
where
R: RangeBounds<usize>,
{
Self { range }
}
pub(crate) fn get_range(&self) -> &R {
&self.range
}
}
impl Columns<()> {
/// Returns a new instance of [`Columns`] for a single column.
///
/// If the boundaries are exceeded it may panic.
pub fn single(index: usize) -> Column {
Column(index)
}
/// Returns a new instance of [`Columns`] for a first column.
///
/// If the boundaries are exceeded the object will produce no cells.
pub fn first() -> FirstColumn {
FirstColumn
}
/// Returns a new instance of [`Columns`] for a last column.
///
/// If the boundaries are exceeded the object will produce no cells.
pub fn last() -> LastColumn {
LastColumn
}
}
impl<I, R> Object<I> for Columns<R>
where
R: RangeBounds<usize>,
I: Records,
{
type Iter = ColumnsIter;
fn cells(&self, records: &I) -> Self::Iter {
let max = records.count_columns();
let start = self.range.start_bound();
let end = self.range.end_bound();
let (x, y) = bounds_to_usize(start, end, max);
ColumnsIter::new(x, y)
}
}
/// `FirstColumn` represents the first column on a grid.
#[derive(Debug)]
pub struct FirstColumn;
impl<I> Object<I> for FirstColumn
where
I: Records + ExactRecords,
{
type Iter = EntityOnce;
fn cells(&self, records: &I) -> Self::Iter {
if records.count_rows() == 0 || records.count_columns() == 0 {
return EntityOnce::new(None);
}
EntityOnce::new(Some(Entity::Column(0)))
}
}
impl Add<usize> for FirstColumn {
type Output = Column;
fn add(self, rhs: usize) -> Self::Output {
Column(rhs)
}
}
/// `LastColumn` represents the last column on a grid.
#[derive(Debug)]
pub struct LastColumn;
impl<I> Object<I> for LastColumn
where
I: Records + ExactRecords,
{
type Iter = EntityOnce;
fn cells(&self, records: &I) -> Self::Iter {
if records.count_rows() == 0 || records.count_columns() == 0 {
return EntityOnce::new(None);
}
let col = records.count_columns().saturating_sub(1);
EntityOnce::new(Some(Entity::Column(col)))
}
}
impl Sub<usize> for LastColumn {
type Output = LastColumnOffset;
fn sub(self, rhs: usize) -> Self::Output {
LastColumnOffset { offset: rhs }
}
}
/// Column represents a single column on a grid.
#[derive(Debug, Clone, Copy)]
pub struct Column(usize);
impl<I> Object<I> for Column {
type Iter = EntityOnce;
fn cells(&self, _: &I) -> Self::Iter {
EntityOnce::new(Some(Entity::Column(self.0)))
}
}
impl From<usize> for Column {
fn from(i: usize) -> Self {
Self(i)
}
}
impl From<Column> for usize {
fn from(val: Column) -> Self {
val.0
}
}
/// `LastColumnOffset` represents a single column on a grid indexed via offset from the last column.
#[derive(Debug)]
pub struct LastColumnOffset {
offset: usize,
}
impl<I> Object<I> for LastColumnOffset
where
I: Records + ExactRecords,
{
type Iter = EntityOnce;
fn cells(&self, records: &I) -> Self::Iter {
if records.count_rows() == 0 || records.count_columns() == 0 {
return EntityOnce::new(None);
}
let col = records.count_columns().saturating_sub(1);
if self.offset > col {
return EntityOnce::new(None);
}
let col = col - self.offset;
EntityOnce::new(Some(Entity::Column(col)))
}
}
/// An [`Iterator`] which goes goes over columns of a [`Table`].
///
/// [`Table`]: crate::Table
#[derive(Debug)]
pub struct ColumnsIter {
start: usize,
end: usize,
}
impl ColumnsIter {
const fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
}
impl Iterator for ColumnsIter {
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::Column(col))
}
}