1//! This module contains an [`Dup`] setting the [`Table`].
2//!
3//! # Example
4//!
5//! ```
6//! # use tabled::{Table, settings::{Dup, object::{Columns, Rows}}};
7//! # let data: Vec<&'static str> = Vec::new();
8//! let mut table = Table::new(&data);
9//! table.with(Dup::new(Rows::first(), Columns::first()));
10//! ```
11//!
12//! [`Table`]: crate::Table
13
14use papergrid::config::Position;
15
16use crate::{
17 grid::records::{ExactRecords, PeekableRecords, Records, RecordsMut},
18 settings::{object::Object, TableOption},
19};
20
21/// [`Dup`] duplicates a given set of cells into another set of ones [`Table`].
22///
23/// # Example
24///
25/// ```
26/// use tabled::{Table, settings::{object::Rows, Dup}};
27///
28/// let data = [
29/// ["1", "2", "3"],
30/// ["Some\nMulti\nLine\nText", "and a line", "here"],
31/// ["4", "5", "6"],
32/// ];
33///
34/// let mut table = Table::new(&data);
35/// table.with(Dup::new(Rows::single(1), Rows::single(2)));
36///
37/// assert_eq!(
38/// table.to_string(),
39/// "+-------+------------+------+\n\
40/// | 0 | 1 | 2 |\n\
41/// +-------+------------+------+\n\
42/// | Some | and a line | here |\n\
43/// | Multi | | |\n\
44/// | Line | | |\n\
45/// | Text | | |\n\
46/// +-------+------------+------+\n\
47/// | Some | and a line | here |\n\
48/// | Multi | | |\n\
49/// | Line | | |\n\
50/// | Text | | |\n\
51/// +-------+------------+------+\n\
52/// | 4 | 5 | 6 |\n\
53/// +-------+------------+------+",
54/// )
55/// ```
56///
57/// [`Table`]: crate::Table
58#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
59pub struct Dup<Dst, Src> {
60 src: Src,
61 dst: Dst,
62}
63
64impl<Dst, Src> Dup<Dst, Src> {
65 /// New creates a new [`Dup`] modifier.
66 ///
67 /// # Example
68 ///
69 /// ```
70 /// # use tabled::{Table, settings::{Dup, object::{Columns, Rows}}};
71 /// # let data: Vec<&'static str> = Vec::new();
72 /// let mut table = Table::new(&data);
73 /// table.with(Dup::new(Rows::first(), Columns::last()));
74 /// ```
75 pub fn new(dst: Dst, src: Src) -> Self {
76 Self { src, dst }
77 }
78}
79
80impl<Dst, Src, R, D, C> TableOption<R, D, C> for Dup<Dst, Src>
81where
82 Dst: Object<R>,
83 Src: Object<R>,
84 R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
85{
86 fn change(self, records: &mut R, _: &mut C, _: &mut D) {
87 let input: Vec = collect_input(records, self.src);
88 set_cells(records, &input, self.dst);
89 }
90}
91
92fn collect_input<R, O>(records: &mut R, src: O) -> Vec<String>
93where
94 O: Object<R>,
95 R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
96{
97 let count_rows: usize = records.count_rows();
98 let count_columns: usize = records.count_columns();
99
100 let mut input: Vec = Vec::new();
101 for entity in src.cells(records) {
102 for pos: (usize, usize) in entity.iter(count_rows, count_columns) {
103 if !is_valid_cell(pos, count_rows, count_columns) {
104 continue;
105 }
106
107 let text: String = records.get_text(pos).to_owned();
108 input.push(text);
109 }
110 }
111
112 input
113}
114
115fn set_cells<R, O>(records: &mut R, src: &[String], dst: O)
116where
117 O: Object<R>,
118 R: Records + ExactRecords + PeekableRecords + RecordsMut<String>,
119{
120 if src.is_empty() {
121 return;
122 }
123
124 let count_rows: usize = records.count_rows();
125 let count_columns: usize = records.count_columns();
126
127 for entity in dst.cells(records) {
128 let mut source: Cycle> = src.iter().cycle();
129 for pos: (usize, usize) in entity.iter(count_rows, count_columns) {
130 if !is_valid_cell(pos, count_rows, count_columns) {
131 continue;
132 }
133
134 let text: String = source.next().unwrap().clone();
135 records.set(pos, text);
136 }
137 }
138}
139
140fn is_valid_cell((row: usize, col: usize): Position, count_rows: usize, count_columns: usize) -> bool {
141 if row > count_rows {
142 return false;
143 }
144
145 if col > count_columns {
146 return false;
147 }
148
149 true
150}
151