//! This module contains an [`Dup`] setting the [`Table`]. //! //! # Example //! //! ``` //! # use tabled::{Table, settings::{Dup, object::{Columns, Rows}}}; //! # let data: Vec<&'static str> = Vec::new(); //! let mut table = Table::new(&data); //! table.with(Dup::new(Rows::first(), Columns::first())); //! ``` //! //! [`Table`]: crate::Table use papergrid::config::Position; use crate::{ grid::records::{ExactRecords, PeekableRecords, Records, RecordsMut}, settings::{object::Object, TableOption}, }; /// [`Dup`] duplicates a given set of cells into another set of ones [`Table`]. /// /// # Example /// /// ``` /// use tabled::{Table, settings::{object::Rows, Dup}}; /// /// let data = [ /// ["1", "2", "3"], /// ["Some\nMulti\nLine\nText", "and a line", "here"], /// ["4", "5", "6"], /// ]; /// /// let mut table = Table::new(&data); /// table.with(Dup::new(Rows::single(1), Rows::single(2))); /// /// assert_eq!( /// table.to_string(), /// "+-------+------------+------+\n\ /// | 0 | 1 | 2 |\n\ /// +-------+------------+------+\n\ /// | Some | and a line | here |\n\ /// | Multi | | |\n\ /// | Line | | |\n\ /// | Text | | |\n\ /// +-------+------------+------+\n\ /// | Some | and a line | here |\n\ /// | Multi | | |\n\ /// | Line | | |\n\ /// | Text | | |\n\ /// +-------+------------+------+\n\ /// | 4 | 5 | 6 |\n\ /// +-------+------------+------+", /// ) /// ``` /// /// [`Table`]: crate::Table #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Dup { src: Src, dst: Dst, } impl Dup { /// New creates a new [`Dup`] modifier. /// /// # Example /// /// ``` /// # use tabled::{Table, settings::{Dup, object::{Columns, Rows}}}; /// # let data: Vec<&'static str> = Vec::new(); /// let mut table = Table::new(&data); /// table.with(Dup::new(Rows::first(), Columns::last())); /// ``` pub fn new(dst: Dst, src: Src) -> Self { Self { src, dst } } } impl TableOption for Dup where Dst: Object, Src: Object, R: Records + ExactRecords + PeekableRecords + RecordsMut, { fn change(self, records: &mut R, _: &mut C, _: &mut D) { let input = collect_input(records, self.src); set_cells(records, &input, self.dst); } } fn collect_input(records: &mut R, src: O) -> Vec where O: Object, R: Records + ExactRecords + PeekableRecords + RecordsMut, { let count_rows = records.count_rows(); let count_columns = records.count_columns(); let mut input = Vec::new(); for entity in src.cells(records) { for pos in entity.iter(count_rows, count_columns) { if !is_valid_cell(pos, count_rows, count_columns) { continue; } let text = records.get_text(pos).to_owned(); input.push(text); } } input } fn set_cells(records: &mut R, src: &[String], dst: O) where O: Object, R: Records + ExactRecords + PeekableRecords + RecordsMut, { if src.is_empty() { return; } let count_rows = records.count_rows(); let count_columns = records.count_columns(); for entity in dst.cells(records) { let mut source = src.iter().cycle(); for pos in entity.iter(count_rows, count_columns) { if !is_valid_cell(pos, count_rows, count_columns) { continue; } let text = source.next().unwrap().clone(); records.set(pos, text); } } } fn is_valid_cell((row, col): Position, count_rows: usize, count_columns: usize) -> bool { if row > count_rows { return false; } if col > count_columns { return false; } true }