tabled/settings/object/
segment.rs

1use std::ops::{RangeBounds, RangeFull};
2
3use papergrid::config::Position;
4
5use crate::{
6    grid::config::Entity,
7    grid::records::{ExactRecords, Records},
8    settings::object::{cell::EntityOnce, Object},
9};
10
11use super::util::bounds_to_usize;
12
13/// This structure represents a sub table of [`Table`].
14///
15/// [`Table`]: crate::Table
16#[derive(Debug)]
17pub struct Segment<C, R> {
18    columns: C,
19    rows: R,
20}
21
22impl Segment<RangeFull, RangeFull> {
23    /// Returns a table segment on which are present all cells.
24    pub fn all() -> SegmentAll {
25        SegmentAll
26    }
27}
28
29impl<C, R> Segment<C, R>
30where
31    C: RangeBounds<usize>,
32    R: RangeBounds<usize>,
33{
34    /// This function builds a [`Segment`].
35    pub fn new(rows: R, columns: C) -> Self {
36        Self { columns, rows }
37    }
38}
39
40impl<I, C, R> Object<I> for Segment<C, R>
41where
42    C: RangeBounds<usize>,
43    R: RangeBounds<usize>,
44    I: Records + ExactRecords,
45{
46    type Iter = SectorIter;
47
48    fn cells(&self, records: &I) -> Self::Iter {
49        let start = self.rows.start_bound();
50        let end = self.rows.end_bound();
51        let max = records.count_rows();
52        let (rows_start, rows_end) = bounds_to_usize(start, end, max);
53
54        let start = self.columns.start_bound();
55        let end = self.columns.end_bound();
56        let max = records.count_columns();
57        let (cols_start, cols_end) = bounds_to_usize(start, end, max);
58
59        SectorIter::new(rows_start, rows_end, cols_start, cols_end)
60    }
61}
62
63/// This is a segment which contains all cells on the table.
64///
65/// Can be created from [`Segment::all`].
66#[derive(Debug)]
67pub struct SegmentAll;
68
69impl<I> Object<I> for SegmentAll {
70    type Iter = EntityOnce;
71
72    fn cells(&self, _: &I) -> Self::Iter {
73        EntityOnce::new(Some(Entity::Global))
74    }
75}
76
77/// An [`Iterator`] which goes goes over all cell in a sector in a [`Table`].
78///
79/// [`Table`]: crate::Table
80#[derive(Debug)]
81pub struct SectorIter {
82    iter: SectorCellsIter,
83}
84
85impl SectorIter {
86    const fn new(rows_start: usize, rows_end: usize, cols_start: usize, cols_end: usize) -> Self {
87        Self {
88            iter: SectorCellsIter::new(rows_start, rows_end, cols_start, cols_end),
89        }
90    }
91}
92
93impl Iterator for SectorIter {
94    type Item = Entity;
95
96    fn next(&mut self) -> Option<Self::Item> {
97        self.iter.next().map(Into::into)
98    }
99}
100
101#[derive(Debug)]
102pub(crate) struct SectorCellsIter {
103    rows_end: usize,
104    cols_start: usize,
105    cols_end: usize,
106    row: usize,
107    col: usize,
108}
109
110impl SectorCellsIter {
111    /// Create an iterator from 1st row to last from 1st col to last.
112    pub(crate) const fn new(
113        rows_start: usize,
114        rows_end: usize,
115        cols_start: usize,
116        cols_end: usize,
117    ) -> Self {
118        Self {
119            rows_end,
120            cols_start,
121            cols_end,
122            row: rows_start,
123            col: cols_start,
124        }
125    }
126}
127
128impl Iterator for SectorCellsIter {
129    type Item = Position;
130
131    fn next(&mut self) -> Option<Self::Item> {
132        if self.row >= self.rows_end {
133            return None;
134        }
135
136        if self.col >= self.cols_end {
137            return None;
138        }
139
140        let row = self.row;
141        let col = self.col;
142
143        self.col += 1;
144
145        if self.col == self.cols_end {
146            self.row += 1;
147            self.col = self.cols_start;
148        }
149
150        Some((row, col).into())
151    }
152}