summaryrefslogtreecommitdiffstats
path: root/vendor/tabled/src/settings/concat
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tabled/src/settings/concat')
-rw-r--r--vendor/tabled/src/settings/concat/mod.rs171
1 files changed, 171 insertions, 0 deletions
diff --git a/vendor/tabled/src/settings/concat/mod.rs b/vendor/tabled/src/settings/concat/mod.rs
new file mode 100644
index 000000000..23b0dcda1
--- /dev/null
+++ b/vendor/tabled/src/settings/concat/mod.rs
@@ -0,0 +1,171 @@
+//! This module contains a [`Concat`] primitive which can be in order to combine 2 [`Table`]s into 1.
+//!
+//! # Example
+//!
+//! ```
+//! use tabled::{Table, settings::Concat};
+//! let table1 = Table::new([0, 1, 2, 3]);
+//! let table2 = Table::new(["A", "B", "C", "D"]);
+//!
+//! let mut table3 = table1;
+//! table3.with(Concat::horizontal(table2));
+//! ```
+
+use std::borrow::Cow;
+
+use crate::{
+ grid::records::{ExactRecords, PeekableRecords, Records, RecordsMut, Resizable},
+ settings::TableOption,
+ Table,
+};
+
+/// [`Concat`] concatenates tables along a particular axis [Horizontal | Vertical].
+/// It doesn't do any key or column comparisons like SQL's join does.
+///
+/// When the tables has different sizes, empty cells will be created by default.
+///
+/// [`Concat`] in horizontal mode has similar behaviour to tuples `(a, b)`.
+/// But it behaves on tables rather than on an actual data.
+///
+/// # Example
+///
+///
+#[cfg_attr(feature = "derive", doc = "```")]
+#[cfg_attr(not(feature = "derive"), doc = "```ignore")]
+/// use tabled::{Table, Tabled, settings::{Style, Concat}};
+///
+/// #[derive(Tabled)]
+/// struct Message {
+/// id: &'static str,
+/// text: &'static str,
+/// }
+///
+/// #[derive(Tabled)]
+/// struct Department(#[tabled(rename = "department")] &'static str);
+///
+/// let messages = [
+/// Message { id: "0", text: "Hello World" },
+/// Message { id: "1", text: "Do do do something", },
+/// ];
+///
+/// let departments = [
+/// Department("Admins"),
+/// Department("DevOps"),
+/// Department("R&D"),
+/// ];
+///
+/// let mut table = Table::new(messages);
+/// table
+/// .with(Concat::horizontal(Table::new(departments)))
+/// .with(Style::extended());
+///
+/// assert_eq!(
+/// table.to_string(),
+/// concat!(
+/// "╔════╦════════════════════╦════════════╗\n",
+/// "║ id ║ text ║ department ║\n",
+/// "╠════╬════════════════════╬════════════╣\n",
+/// "║ 0 ║ Hello World ║ Admins ║\n",
+/// "╠════╬════════════════════╬════════════╣\n",
+/// "║ 1 ║ Do do do something ║ DevOps ║\n",
+/// "╠════╬════════════════════╬════════════╣\n",
+/// "║ ║ ║ R&D ║\n",
+/// "╚════╩════════════════════╩════════════╝",
+/// )
+/// )
+/// ```
+
+#[derive(Debug)]
+pub struct Concat {
+ table: Table,
+ mode: ConcatMode,
+ default_cell: Cow<'static, str>,
+}
+
+#[derive(Debug)]
+enum ConcatMode {
+ Vertical,
+ Horizontal,
+}
+
+impl Concat {
+ fn new(table: Table, mode: ConcatMode) -> Self {
+ Self {
+ table,
+ mode,
+ default_cell: Cow::Borrowed(""),
+ }
+ }
+
+ /// Concatenate 2 tables horizontally (along axis=0)
+ pub fn vertical(table: Table) -> Self {
+ Self::new(table, ConcatMode::Vertical)
+ }
+
+ /// Concatenate 2 tables vertically (along axis=1)
+ pub fn horizontal(table: Table) -> Self {
+ Self::new(table, ConcatMode::Horizontal)
+ }
+
+ /// Sets a cell's content for cases where 2 tables has different sizes.
+ pub fn default_cell(mut self, cell: impl Into<Cow<'static, str>>) -> Self {
+ self.default_cell = cell.into();
+ self
+ }
+}
+
+impl<R, D, C> TableOption<R, D, C> for Concat
+where
+ R: Records + ExactRecords + Resizable + PeekableRecords + RecordsMut<String>,
+{
+ fn change(mut self, records: &mut R, _: &mut C, _: &mut D) {
+ let count_rows = records.count_rows();
+ let count_cols = records.count_columns();
+
+ let rhs = &mut self.table;
+ match self.mode {
+ ConcatMode::Horizontal => {
+ for _ in 0..rhs.count_columns() {
+ records.push_column();
+ }
+
+ for row in count_rows..rhs.count_rows() {
+ records.push_row();
+
+ for col in 0..records.count_columns() {
+ records.set((row, col), self.default_cell.to_string());
+ }
+ }
+
+ for row in 0..rhs.shape().0 {
+ for col in 0..rhs.shape().1 {
+ let text = rhs.get_records().get_text((row, col)).to_string();
+ let col = col + count_cols;
+ records.set((row, col), text);
+ }
+ }
+ }
+ ConcatMode::Vertical => {
+ for _ in 0..rhs.count_rows() {
+ records.push_row();
+ }
+
+ for col in count_cols..rhs.shape().1 {
+ records.push_column();
+
+ for row in 0..records.count_rows() {
+ records.set((row, col), self.default_cell.to_string());
+ }
+ }
+
+ for row in 0..rhs.shape().0 {
+ for col in 0..rhs.shape().1 {
+ let text = rhs.get_records().get_text((row, col)).to_string();
+ let row = row + count_rows;
+ records.set((row, col), text);
+ }
+ }
+ }
+ }
+ }
+}