use std::ops::{RangeBounds, RangeFull};
use papergrid::records::{Records, Resizable};
use crate::{object::bounds_to_usize, Table, TableOption};
#[derive(Debug)]
pub struct Extract<R, C> {
rows: R,
columns: C,
}
impl<R, C> Extract<R, C>
where
R: RangeBounds<usize>,
C: RangeBounds<usize>,
{
pub fn segment(rows: R, columns: C) -> Self {
Extract { rows, columns }
}
}
impl<R> Extract<R, RangeFull>
where
R: RangeBounds<usize>,
{
pub fn rows(rows: R) -> Self {
Extract { rows, columns: .. }
}
}
impl<C> Extract<RangeFull, C>
where
C: RangeBounds<usize>,
{
pub fn columns(columns: C) -> Self {
Extract { rows: .., columns }
}
}
impl<R, C, RR> TableOption<RR> for Extract<R, C>
where
R: RangeBounds<usize> + Clone,
C: RangeBounds<usize> + Clone,
RR: Records + Resizable,
{
fn change(&mut self, table: &mut Table<RR>) {
let shape = table.shape();
let mut rows = bounds_to_usize(self.rows.start_bound(), self.rows.end_bound(), shape.0);
let mut cols = bounds_to_usize(
self.columns.start_bound(),
self.columns.end_bound(),
shape.1,
);
rows.0 = std::cmp::min(rows.0, shape.0);
cols.0 = std::cmp::min(cols.0, shape.1);
extract(table.get_records_mut(), shape, rows, cols);
}
}
fn extract<R>(
records: &mut R,
(count_rows, count_cols): (usize, usize),
(start_row, end_row): (usize, usize),
(start_col, end_col): (usize, usize),
) where
R: Resizable,
{
for (i, row) in (0..start_row).enumerate() {
let row = row - i;
records.remove_row(row);
}
let count_rows = count_rows - start_row;
let end_row = end_row - start_row;
for (i, row) in (end_row..count_rows).enumerate() {
let row = row - i;
records.remove_row(row);
}
for (i, col) in (0..start_col).enumerate() {
let col = col - i;
records.remove_column(col);
}
let count_cols = count_cols - start_col;
let end_col = end_col - start_col;
for (i, col) in (end_col..count_cols).enumerate() {
let col = col - i;
records.remove_column(col);
}
}