summaryrefslogtreecommitdiffstats
path: root/vendor/tabled/src/grid
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tabled/src/grid')
-rw-r--r--vendor/tabled/src/grid/colored_config.rs112
-rw-r--r--vendor/tabled/src/grid/compact_multiline_config.rs211
-rw-r--r--vendor/tabled/src/grid/dimension/complete_dimension.rs136
-rw-r--r--vendor/tabled/src/grid/dimension/complete_dimension_vec_records.rs128
-rw-r--r--vendor/tabled/src/grid/dimension/const_dimension.rs70
-rw-r--r--vendor/tabled/src/grid/dimension/mod.rs32
-rw-r--r--vendor/tabled/src/grid/dimension/peekable_dimension.rs335
-rw-r--r--vendor/tabled/src/grid/dimension/pool_table_dimension.rs36
-rw-r--r--vendor/tabled/src/grid/dimension/static_dimension.rs63
-rw-r--r--vendor/tabled/src/grid/mod.rs48
-rw-r--r--vendor/tabled/src/grid/records/empty_records.rs41
-rw-r--r--vendor/tabled/src/grid/records/into_records/buf_records.rs213
-rw-r--r--vendor/tabled/src/grid/records/into_records/either_string.rs22
-rw-r--r--vendor/tabled/src/grid/records/into_records/limit_column_records.rs82
-rw-r--r--vendor/tabled/src/grid/records/into_records/limit_row_records.rs59
-rw-r--r--vendor/tabled/src/grid/records/into_records/mod.rs26
-rw-r--r--vendor/tabled/src/grid/records/into_records/truncate_records.rs136
-rw-r--r--vendor/tabled/src/grid/records/mod.rs19
-rw-r--r--vendor/tabled/src/grid/records/records_mut.rs34
-rw-r--r--vendor/tabled/src/grid/records/resizable.rs217
20 files changed, 2020 insertions, 0 deletions
diff --git a/vendor/tabled/src/grid/colored_config.rs b/vendor/tabled/src/grid/colored_config.rs
new file mode 100644
index 000000000..51a00fbf4
--- /dev/null
+++ b/vendor/tabled/src/grid/colored_config.rs
@@ -0,0 +1,112 @@
+use std::ops::{Deref, DerefMut};
+
+use crate::grid::{
+ color::AnsiColor,
+ config::{Entity, EntityMap, SpannedConfig},
+};
+
+/// A spanned configuration plus colors for cells.
+#[derive(Debug, Default, PartialEq, Eq, Clone)]
+pub struct ColoredConfig {
+ config: SpannedConfig,
+ colors: ColorMap,
+}
+
+impl ColoredConfig {
+ /// Create a new colored config.
+ pub fn new(config: SpannedConfig) -> Self {
+ Self {
+ config,
+ colors: ColorMap::default(),
+ }
+ }
+
+ /// Set a color for a given cell.
+ ///
+ /// The outcome is the same as if you'd use [`Format`] and added a color but it'd work only with `color` feature on.
+ /// While this method works in all contexts.
+ ///
+ /// [`Format`]: crate::settings::Format
+ pub fn set_color(&mut self, pos: Entity, color: AnsiColor<'static>) -> &mut Self {
+ match self.colors.0.as_mut() {
+ Some(map) => map.insert(pos, color),
+ None => {
+ let mut colors = EntityMap::default();
+ colors.insert(pos, color);
+ self.colors = ColorMap(Some(colors));
+ }
+ }
+
+ self
+ }
+
+ /// Set a list of colors.
+ pub fn set_colors(&mut self, colors: EntityMap<AnsiColor<'static>>) -> &mut Self {
+ self.colors = ColorMap(Some(colors));
+ self
+ }
+
+ /// Remove a color for a given cell.
+ pub fn remove_color(&mut self, pos: Entity) -> &mut Self {
+ if let Some(colors) = self.colors.0.as_mut() {
+ colors.remove(pos);
+ }
+
+ self
+ }
+
+ /// Returns a list of colors.
+ pub fn get_colors(&self) -> &ColorMap {
+ &self.colors
+ }
+
+ /// Returns an inner config.
+ pub fn into_inner(self) -> SpannedConfig {
+ self.config
+ }
+}
+
+impl Deref for ColoredConfig {
+ type Target = SpannedConfig;
+
+ fn deref(&self) -> &Self::Target {
+ &self.config
+ }
+}
+
+impl DerefMut for ColoredConfig {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.config
+ }
+}
+
+impl From<SpannedConfig> for ColoredConfig {
+ fn from(value: SpannedConfig) -> Self {
+ Self::new(value)
+ }
+}
+
+impl AsRef<SpannedConfig> for ColoredConfig {
+ fn as_ref(&self) -> &SpannedConfig {
+ &self.config
+ }
+}
+
+/// A colors structure for [`ColoredConfig`].
+#[derive(Debug, Default, PartialEq, Eq, Clone)]
+pub struct ColorMap(Option<EntityMap<AnsiColor<'static>>>);
+
+impl ColorMap {
+ /// Checks if any colors is set on.
+ pub fn is_empty(&self) -> bool {
+ self.0.is_none()
+ }
+}
+
+impl crate::grid::colors::Colors for ColorMap {
+ type Color = AnsiColor<'static>;
+
+ fn get_color(&self, (row, col): (usize, usize)) -> Option<&Self::Color> {
+ self.0.as_ref().map(|map| map.get(Entity::Cell(row, col)))
+ }
+}
diff --git a/vendor/tabled/src/grid/compact_multiline_config.rs b/vendor/tabled/src/grid/compact_multiline_config.rs
new file mode 100644
index 000000000..c9056c911
--- /dev/null
+++ b/vendor/tabled/src/grid/compact_multiline_config.rs
@@ -0,0 +1,211 @@
+use crate::grid::color::StaticColor;
+use crate::grid::config::{
+ AlignmentHorizontal, AlignmentVertical, Borders, CompactConfig, Indent, Line, Sides,
+};
+
+/// A [`CompactConfig`] configuration plus vertical alignment.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct CompactMultilineConfig {
+ config: CompactConfig,
+ alignment_vertical: AlignmentVertical,
+ formatting: Formatting,
+}
+
+impl CompactMultilineConfig {
+ /// Create a new colored config.
+ pub fn new(config: CompactConfig) -> Self {
+ Self::from(config)
+ }
+
+ /// Set a horizontal alignment.
+ pub const fn set_alignment_vertical(mut self, alignment: AlignmentVertical) -> Self {
+ self.alignment_vertical = alignment;
+ self
+ }
+
+ /// Get a alignment horizontal.
+ pub const fn get_alignment_vertical(&self) -> AlignmentVertical {
+ self.alignment_vertical
+ }
+
+ /// Set grid margin.
+ pub const fn set_margin(mut self, margin: Sides<Indent>) -> Self {
+ self.config = self.config.set_margin(margin);
+ self
+ }
+
+ /// Returns a grid margin.
+ pub const fn get_margin(&self) -> &Sides<Indent> {
+ self.config.get_margin()
+ }
+
+ /// Set the [`Borders`] value as correct one.
+ pub const fn set_borders(mut self, borders: Borders<char>) -> Self {
+ self.config = self.config.set_borders(borders);
+ self
+ }
+
+ /// Set the first horizontal line.
+ ///
+ /// It ignores the [`Borders`] horizontal value if set for 1st row.
+ pub const fn set_first_horizontal_line(mut self, line: Line<char>) -> Self {
+ self.config = self.config.set_first_horizontal_line(line);
+ self
+ }
+
+ /// Set the first horizontal line.
+ ///
+ /// It ignores the [`Borders`] horizontal value if set for 1st row.
+ pub const fn get_first_horizontal_line(&self) -> Option<Line<char>> {
+ self.config.get_first_horizontal_line()
+ }
+
+ /// Returns a current [`Borders`] structure.
+ pub const fn get_borders(&self) -> &Borders<char> {
+ self.config.get_borders()
+ }
+
+ /// Returns a current [`Borders`] structure.
+ pub const fn get_borders_color(&self) -> &Borders<StaticColor> {
+ self.config.get_borders_color()
+ }
+
+ /// Set a padding to a given cells.
+ pub const fn set_padding(mut self, padding: Sides<Indent>) -> Self {
+ self.config = self.config.set_padding(padding);
+ self
+ }
+
+ /// Get a padding for a given.
+ pub const fn get_padding(&self) -> &Sides<Indent> {
+ self.config.get_padding()
+ }
+
+ /// Set a horizontal alignment.
+ pub const fn set_alignment_horizontal(mut self, alignment: AlignmentHorizontal) -> Self {
+ self.config = self.config.set_alignment_horizontal(alignment);
+ self
+ }
+
+ /// Get a alignment horizontal.
+ pub const fn get_alignment_horizontal(&self) -> AlignmentHorizontal {
+ self.config.get_alignment_horizontal()
+ }
+
+ /// Sets colors of border carcass on the grid.
+ pub const fn set_borders_color(mut self, borders: Borders<StaticColor>) -> Self {
+ self.config = self.config.set_borders_color(borders);
+ self
+ }
+
+ /// Set colors for a margin.
+ pub const fn set_margin_color(mut self, color: Sides<StaticColor>) -> Self {
+ self.config = self.config.set_margin_color(color);
+ self
+ }
+
+ /// Returns a margin color.
+ pub const fn get_margin_color(&self) -> Sides<StaticColor> {
+ self.config.get_margin_color()
+ }
+
+ /// Set a padding color to all cells.
+ pub const fn set_padding_color(mut self, color: Sides<StaticColor>) -> Self {
+ self.config = self.config.set_padding_color(color);
+ self
+ }
+
+ /// get a padding color.
+ pub const fn get_padding_color(&self) -> Sides<StaticColor> {
+ self.config.get_padding_color()
+ }
+
+ /// Set formatting.
+ pub const fn set_formatting(mut self, formatting: Formatting) -> Self {
+ self.formatting = formatting;
+ self
+ }
+
+ /// Get formatting.
+ pub const fn get_formatting(&self) -> Formatting {
+ self.formatting
+ }
+}
+
+impl Default for CompactMultilineConfig {
+ fn default() -> Self {
+ Self {
+ config: Default::default(),
+ alignment_vertical: AlignmentVertical::Top,
+ formatting: Formatting::default(),
+ }
+ }
+}
+
+impl From<CompactConfig> for CompactMultilineConfig {
+ fn from(config: CompactConfig) -> Self {
+ Self {
+ config,
+ alignment_vertical: AlignmentVertical::Top,
+ formatting: Formatting::default(),
+ }
+ }
+}
+
+impl AsRef<CompactConfig> for CompactMultilineConfig {
+ fn as_ref(&self) -> &CompactConfig {
+ &self.config
+ }
+}
+
+impl AsMut<CompactConfig> for CompactMultilineConfig {
+ fn as_mut(&mut self) -> &mut CompactConfig {
+ &mut self.config
+ }
+}
+
+#[cfg(feature = "std")]
+impl From<CompactMultilineConfig> for crate::grid::config::SpannedConfig {
+ fn from(compact: CompactMultilineConfig) -> Self {
+ use crate::grid::config::Entity;
+
+ let mut cfg = crate::grid::config::SpannedConfig::from(compact.config);
+ cfg.set_alignment_vertical(Entity::Global, compact.alignment_vertical);
+ cfg.set_formatting(Entity::Global, compact.formatting.into());
+
+ cfg
+ }
+}
+
+/// Formatting represent a logic of formatting of a cell.
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Formatting {
+ /// An setting to allow horizontal trim.
+ pub horizontal_trim: bool,
+ /// An setting to allow vertical trim.
+ pub vertical_trim: bool,
+ /// An setting to allow alignment per line.
+ pub allow_lines_alignment: bool,
+}
+
+impl Formatting {
+ /// Creates a new [`Formatting`] structure.
+ pub fn new(horizontal_trim: bool, vertical_trim: bool, allow_lines_alignment: bool) -> Self {
+ Self {
+ horizontal_trim,
+ vertical_trim,
+ allow_lines_alignment,
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl From<Formatting> for crate::grid::config::Formatting {
+ fn from(val: Formatting) -> Self {
+ crate::grid::config::Formatting {
+ allow_lines_alignment: val.allow_lines_alignment,
+ horizontal_trim: val.horizontal_trim,
+ vertical_trim: val.vertical_trim,
+ }
+ }
+}
diff --git a/vendor/tabled/src/grid/dimension/complete_dimension.rs b/vendor/tabled/src/grid/dimension/complete_dimension.rs
new file mode 100644
index 000000000..3147cb27a
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/complete_dimension.rs
@@ -0,0 +1,136 @@
+use std::borrow::Cow;
+
+use crate::grid::{
+ config::{ColoredConfig, SpannedConfig},
+ dimension::{Dimension, Estimate, SpannedGridDimension},
+ records::Records,
+};
+
+/// CompleteDimension is a [`Dimension`] implementation for a [`Table`]
+///
+/// [`Table`]: crate::Table
+#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
+pub struct CompleteDimension<'a> {
+ width: Option<Cow<'a, [usize]>>,
+ height: Option<Cow<'a, [usize]>>,
+}
+
+impl CompleteDimension<'_> {
+ /// Checks whether is the dimensions is set.
+ pub fn is_complete(&self) -> bool {
+ self.width.is_some() && self.height.is_some()
+ }
+
+ /// Checks whether is nothing was set.
+ pub fn is_empty(&self) -> bool {
+ self.width.is_none() && self.height.is_none()
+ }
+
+ /// Set column widths.
+ ///
+ /// In general the method is only considered to be useful to a [`TableOption`].
+ ///
+ /// BE CAREFUL WITH THIS METHOD as it supposed that the content is not bigger than the provided widths.
+ ///
+ /// [`TableOption`]: crate::settings::TableOption
+ pub fn set_widths(&mut self, columns: Vec<usize>) -> bool {
+ self.width = Some(Cow::Owned(columns));
+
+ true
+ }
+
+ /// Set rows heights.
+ ///
+ /// In general the method is only considered to be useful to a [`TableOption`].
+ ///
+ /// BE CAREFUL WITH THIS METHOD as it supposed that the content is not bigger than the provided heights.
+ ///
+ /// [`TableOption`]: crate::settings::TableOption
+ pub fn set_heights(&mut self, rows: Vec<usize>) -> bool {
+ self.height = Some(Cow::Owned(rows));
+
+ true
+ }
+
+ /// Force width estimation.
+ pub fn clear_width(&mut self) {
+ self.width = None;
+ }
+
+ /// Force height estimation.
+ pub fn clear_height(&mut self) {
+ self.height = None;
+ }
+
+ /// Copies a reference from self.
+ pub fn from_origin(&self) -> CompleteDimension<'_> {
+ let width = self.width.as_deref().map(Cow::Borrowed);
+ let height = self.height.as_deref().map(Cow::Borrowed);
+
+ CompleteDimension { width, height }
+ }
+}
+
+impl Dimension for CompleteDimension<'_> {
+ fn get_width(&self, column: usize) -> usize {
+ let width = self
+ .width
+ .as_ref()
+ .expect("It must always be Some at this point");
+
+ width[column]
+ }
+
+ fn get_height(&self, row: usize) -> usize {
+ let height = self
+ .height
+ .as_ref()
+ .expect("It must always be Some at this point");
+
+ height[row]
+ }
+}
+
+impl<R: Records> Estimate<R, SpannedConfig> for CompleteDimension<'_> {
+ fn estimate(&mut self, records: R, cfg: &SpannedConfig) {
+ match (self.width.is_some(), self.height.is_some()) {
+ (true, true) => {}
+ (true, false) => {
+ self.height = Some(Cow::Owned(SpannedGridDimension::height(records, cfg)));
+ }
+ (false, true) => {
+ self.width = Some(Cow::Owned(SpannedGridDimension::width(records, cfg)));
+ }
+ (false, false) => {
+ let mut dims = SpannedGridDimension::default();
+ dims.estimate(records, cfg);
+
+ let (width, height) = dims.get_values();
+ self.width = Some(Cow::Owned(width));
+ self.height = Some(Cow::Owned(height));
+ }
+ }
+ }
+}
+
+impl<R: Records> Estimate<R, ColoredConfig> for CompleteDimension<'_> {
+ fn estimate(&mut self, records: R, cfg: &ColoredConfig) {
+ match (self.width.is_some(), self.height.is_some()) {
+ (true, true) => {}
+ (true, false) => {
+ self.height = Some(Cow::Owned(SpannedGridDimension::height(records, cfg)));
+ }
+ (false, true) => {
+ self.width = Some(Cow::Owned(SpannedGridDimension::width(records, cfg)));
+ }
+ (false, false) => {
+ let mut dims = SpannedGridDimension::default();
+ dims.estimate(records, cfg);
+
+ let (width, height) = dims.get_values();
+ self.width = Some(Cow::Owned(width));
+ self.height = Some(Cow::Owned(height));
+ }
+ }
+ }
+}
diff --git a/vendor/tabled/src/grid/dimension/complete_dimension_vec_records.rs b/vendor/tabled/src/grid/dimension/complete_dimension_vec_records.rs
new file mode 100644
index 000000000..ddc806a45
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/complete_dimension_vec_records.rs
@@ -0,0 +1,128 @@
+use std::borrow::Cow;
+
+use papergrid::{
+ dimension::spanned_vec_records::SpannedVecRecordsDimension, records::vec_records::VecRecords,
+};
+
+use crate::grid::{
+ config::{ColoredConfig, SpannedConfig},
+ dimension::{Dimension, Estimate},
+ records::vec_records::Cell,
+};
+
+/// CompleteDimension is a [`Dimension`] implementation for a [`Table`]
+///
+/// [`Table`]: crate::Table
+#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
+pub struct CompleteDimensionVecRecords<'a> {
+ width: Option<Cow<'a, [usize]>>,
+ height: Option<Cow<'a, [usize]>>,
+}
+
+impl CompleteDimensionVecRecords<'_> {
+ /// Checks whether is the dimensions is set.
+ pub fn is_complete(&self) -> bool {
+ self.width.is_some() && self.height.is_some()
+ }
+
+ /// Checks whether is nothing was set.
+ pub fn is_empty(&self) -> bool {
+ self.width.is_none() && self.height.is_none()
+ }
+
+ /// Set column widths.
+ ///
+ /// In general the method is only considered to be useful to a [`TableOption`].
+ ///
+ /// BE CAREFUL WITH THIS METHOD as it supposed that the content is not bigger than the provided widths.
+ ///
+ /// [`TableOption`]: crate::settings::TableOption
+ pub fn set_widths(&mut self, columns: Vec<usize>) -> bool {
+ self.width = Some(Cow::Owned(columns));
+
+ true
+ }
+
+ /// Set rows heights.
+ ///
+ /// In general the method is only considered to be useful to a [`TableOption`].
+ ///
+ /// BE CAREFUL WITH THIS METHOD as it supposed that the content is not bigger than the provided heights.
+ ///
+ /// [`TableOption`]: crate::settings::TableOption
+ pub fn set_heights(&mut self, rows: Vec<usize>) -> bool {
+ self.height = Some(Cow::Owned(rows));
+
+ true
+ }
+
+ /// Force width estimation.
+ pub fn clear_width(&mut self) {
+ self.width = None;
+ }
+
+ /// Force height estimation.
+ pub fn clear_height(&mut self) {
+ self.height = None;
+ }
+
+ /// Copies a reference from self.
+ pub fn from_origin(&self) -> CompleteDimensionVecRecords<'_> {
+ let width = self.width.as_deref().map(Cow::Borrowed);
+ let height = self.height.as_deref().map(Cow::Borrowed);
+
+ CompleteDimensionVecRecords { width, height }
+ }
+}
+
+impl Dimension for CompleteDimensionVecRecords<'_> {
+ fn get_width(&self, column: usize) -> usize {
+ let width = self
+ .width
+ .as_ref()
+ .expect("It must always be Some at this point");
+
+ width[column]
+ }
+
+ fn get_height(&self, row: usize) -> usize {
+ let height = self
+ .height
+ .as_ref()
+ .expect("It must always be Some at this point");
+
+ height[row]
+ }
+}
+
+impl<T: AsRef<str> + Cell> Estimate<&VecRecords<T>, SpannedConfig>
+ for CompleteDimensionVecRecords<'_>
+{
+ fn estimate(&mut self, records: &VecRecords<T>, cfg: &SpannedConfig) {
+ match (self.width.is_some(), self.height.is_some()) {
+ (true, true) => {}
+ (true, false) => {
+ self.height = Some(Cow::Owned(SpannedVecRecordsDimension::height(records, cfg)));
+ }
+ (false, true) => {
+ self.width = Some(Cow::Owned(SpannedVecRecordsDimension::width(records, cfg)));
+ }
+ (false, false) => {
+ let mut dims = SpannedVecRecordsDimension::default();
+ dims.estimate(records, cfg);
+
+ let (width, height) = dims.get_values();
+ self.width = Some(Cow::Owned(width));
+ self.height = Some(Cow::Owned(height));
+ }
+ }
+ }
+}
+
+impl<T: AsRef<str> + Cell> Estimate<&VecRecords<T>, ColoredConfig>
+ for CompleteDimensionVecRecords<'_>
+{
+ fn estimate(&mut self, records: &VecRecords<T>, cfg: &ColoredConfig) {
+ self.estimate(records, cfg.as_ref())
+ }
+}
diff --git a/vendor/tabled/src/grid/dimension/const_dimension.rs b/vendor/tabled/src/grid/dimension/const_dimension.rs
new file mode 100644
index 000000000..450b1abfe
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/const_dimension.rs
@@ -0,0 +1,70 @@
+//! Module contains a dimension estimator for [`CompactTable`]
+//!
+//! [`CompactTable`]: crate::tables::CompactTable
+
+use crate::grid::dimension::{Dimension, Estimate};
+
+/// A constant size dimension or a value dimension.
+#[derive(Debug, Clone, Copy)]
+pub struct ConstDimension<const COLUMNS: usize, const ROWS: usize> {
+ height: ConstSize<ROWS>,
+ width: ConstSize<COLUMNS>,
+}
+
+impl<const COLUMNS: usize, const ROWS: usize> ConstDimension<COLUMNS, ROWS> {
+ /// Returns a new dimension object with a given estimates.
+ pub const fn new(width: ConstSize<COLUMNS>, height: ConstSize<ROWS>) -> Self {
+ Self { width, height }
+ }
+}
+
+impl<const COLUMNS: usize, const ROWS: usize> Dimension for ConstDimension<COLUMNS, ROWS> {
+ fn get_width(&self, column: usize) -> usize {
+ match self.width {
+ ConstSize::List(list) => list[column],
+ ConstSize::Value(val) => val,
+ }
+ }
+
+ fn get_height(&self, row: usize) -> usize {
+ match self.height {
+ ConstSize::List(list) => list[row],
+ ConstSize::Value(val) => val,
+ }
+ }
+}
+
+impl<const COLUMNS: usize, const ROWS: usize> From<ConstDimension<COLUMNS, ROWS>>
+ for (ConstSize<COLUMNS>, ConstSize<ROWS>)
+{
+ fn from(value: ConstDimension<COLUMNS, ROWS>) -> Self {
+ (value.width, value.height)
+ }
+}
+
+impl<R, D, const COLUMNS: usize, const ROWS: usize> Estimate<R, D>
+ for ConstDimension<COLUMNS, ROWS>
+{
+ fn estimate(&mut self, _: R, _: &D) {}
+}
+
+/// Const size represents either a const array values or a single value which responsible for the whole list.
+#[derive(Debug, Clone, Copy)]
+pub enum ConstSize<const N: usize> {
+ /// A constant array of estimates.
+ List([usize; N]),
+ /// A value which act as a single estimate for all entries.
+ Value(usize),
+}
+
+impl From<usize> for ConstSize<0> {
+ fn from(value: usize) -> Self {
+ ConstSize::Value(value)
+ }
+}
+
+impl<const N: usize> From<[usize; N]> for ConstSize<N> {
+ fn from(value: [usize; N]) -> Self {
+ ConstSize::List(value)
+ }
+}
diff --git a/vendor/tabled/src/grid/dimension/mod.rs b/vendor/tabled/src/grid/dimension/mod.rs
new file mode 100644
index 000000000..2f67b402f
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/mod.rs
@@ -0,0 +1,32 @@
+//! Module contains a list of implementations of [`Estimate`] and [`Dimension`].
+
+mod const_dimension;
+mod pool_table_dimension;
+
+#[cfg(feature = "std")]
+mod complete_dimension;
+#[cfg(feature = "std")]
+mod complete_dimension_vec_records;
+#[cfg(feature = "std")]
+mod peekable_dimension;
+#[cfg(feature = "std")]
+mod static_dimension;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use self::{
+ complete_dimension::CompleteDimension,
+ complete_dimension_vec_records::CompleteDimensionVecRecords,
+ peekable_dimension::PeekableDimension,
+ static_dimension::{DimensionValue, StaticDimension},
+};
+pub use const_dimension::{ConstDimension, ConstSize};
+pub use papergrid::dimension::{Dimension, Estimate};
+pub use pool_table_dimension::{DimensionPriority, PoolTableDimension};
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use papergrid::dimension::{
+ compact::CompactGridDimension, spanned::SpannedGridDimension,
+ spanned_vec_records::SpannedVecRecordsDimension,
+};
diff --git a/vendor/tabled/src/grid/dimension/peekable_dimension.rs b/vendor/tabled/src/grid/dimension/peekable_dimension.rs
new file mode 100644
index 000000000..1ba6fda21
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/peekable_dimension.rs
@@ -0,0 +1,335 @@
+use papergrid::records::vec_records::{CellInfo, VecRecords};
+
+use crate::grid::{
+ config::SpannedConfig,
+ dimension::{Dimension, Estimate},
+ records::Records,
+};
+
+/// PeekableDimension is a [`Dimension`] implementation for a [`Table`]
+///
+/// [`Table`]: crate::Table
+#[derive(Debug, Default, Clone)]
+pub struct PeekableDimension {
+ width: Vec<usize>,
+ height: Vec<usize>,
+}
+
+impl PeekableDimension {
+ /// Calculates height of rows.
+ pub fn height<T: AsRef<str>>(
+ records: &VecRecords<CellInfo<T>>,
+ cfg: &SpannedConfig,
+ ) -> Vec<usize> {
+ estimation::build_height(records, cfg)
+ }
+
+ /// Calculates width of columns.
+ pub fn width<T: AsRef<str>>(
+ records: &VecRecords<CellInfo<T>>,
+ cfg: &SpannedConfig,
+ ) -> Vec<usize> {
+ estimation::build_width(records, cfg)
+ }
+
+ /// Return width and height lists.
+ pub fn get_values(self) -> (Vec<usize>, Vec<usize>) {
+ (self.width, self.height)
+ }
+}
+
+impl Dimension for PeekableDimension {
+ fn get_width(&self, column: usize) -> usize {
+ self.width[column]
+ }
+
+ fn get_height(&self, row: usize) -> usize {
+ self.height[row]
+ }
+}
+
+impl<T> Estimate<&VecRecords<CellInfo<T>>, SpannedConfig> for PeekableDimension
+where
+ T: AsRef<str>,
+{
+ fn estimate(&mut self, records: &VecRecords<CellInfo<T>>, cfg: &SpannedConfig) {
+ let (width, height) = estimation::build_dimensions(records, cfg);
+ self.width = width;
+ self.height = height;
+ }
+}
+
+mod estimation {
+ use core::cmp::{max, Ordering};
+ use std::collections::HashMap;
+
+ use papergrid::{
+ config::Position,
+ records::vec_records::{Cell, CellInfo, VecRecords},
+ };
+
+ use super::*;
+
+ pub(super) fn build_dimensions<T: AsRef<str>>(
+ records: &VecRecords<CellInfo<T>>,
+ cfg: &SpannedConfig,
+ ) -> (Vec<usize>, Vec<usize>) {
+ let count_columns = records.count_columns();
+
+ let mut widths = vec![0; count_columns];
+ let mut heights = vec![];
+
+ let mut vspans = HashMap::new();
+ let mut hspans = HashMap::new();
+
+ for (row, columns) in records.iter_rows().enumerate() {
+ let mut row_height = 0;
+ for (col, cell) in columns.iter().enumerate() {
+ let pos = (row, col);
+ if !cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ let height = cell.count_lines();
+ let width = cell.width();
+
+ let pad = cfg.get_padding(pos.into());
+ let width = width + pad.left.size + pad.right.size;
+ let height = height + pad.top.size + pad.bottom.size;
+
+ match cfg.get_column_span(pos) {
+ Some(n) if n > 1 => {
+ let _ = vspans.insert(pos, (n, width));
+ }
+ _ => widths[col] = max(widths[col], width),
+ }
+
+ match cfg.get_row_span(pos) {
+ Some(n) if n > 1 => {
+ let _ = hspans.insert(pos, (n, height));
+ }
+ _ => row_height = max(row_height, height),
+ }
+ }
+
+ heights.push(row_height);
+ }
+
+ let count_rows = heights.len();
+
+ adjust_vspans(cfg, count_columns, &vspans, &mut widths);
+ adjust_hspans(cfg, count_rows, &hspans, &mut heights);
+
+ (widths, heights)
+ }
+
+ fn adjust_hspans(
+ cfg: &SpannedConfig,
+ len: usize,
+ spans: &HashMap<Position, (usize, usize)>,
+ heights: &mut [usize],
+ ) {
+ if spans.is_empty() {
+ return;
+ }
+
+ let mut spans_ordered = spans
+ .iter()
+ .map(|(k, v)| ((k.0, k.1), *v))
+ .collect::<Vec<_>>();
+ spans_ordered.sort_unstable_by(|(arow, acol), (brow, bcol)| match arow.cmp(brow) {
+ Ordering::Equal => acol.cmp(bcol),
+ ord => ord,
+ });
+
+ for ((row, _), (span, height)) in spans_ordered {
+ adjust_row_range(cfg, height, len, row, row + span, heights);
+ }
+ }
+
+ fn adjust_row_range(
+ cfg: &SpannedConfig,
+ max_span_height: usize,
+ len: usize,
+ start: usize,
+ end: usize,
+ heights: &mut [usize],
+ ) {
+ let range_height = range_height(cfg, len, start, end, heights);
+ if range_height >= max_span_height {
+ return;
+ }
+
+ inc_range(heights, max_span_height - range_height, start, end);
+ }
+
+ fn range_height(
+ cfg: &SpannedConfig,
+ len: usize,
+ start: usize,
+ end: usize,
+ heights: &[usize],
+ ) -> usize {
+ let count_borders = count_horizontal_borders(cfg, len, start, end);
+ let range_height = heights[start..end].iter().sum::<usize>();
+ count_borders + range_height
+ }
+
+ fn count_horizontal_borders(
+ cfg: &SpannedConfig,
+ len: usize,
+ start: usize,
+ end: usize,
+ ) -> usize {
+ (start..end)
+ .skip(1)
+ .filter(|&i| cfg.has_horizontal(i, len))
+ .count()
+ }
+
+ fn inc_range(list: &mut [usize], size: usize, start: usize, end: usize) {
+ if list.is_empty() {
+ return;
+ }
+
+ let span = end - start;
+ let one = size / span;
+ let rest = size - span * one;
+
+ let mut i = start;
+ while i < end {
+ if i == start {
+ list[i] += one + rest;
+ } else {
+ list[i] += one;
+ }
+
+ i += 1;
+ }
+ }
+
+ fn adjust_vspans(
+ cfg: &SpannedConfig,
+ len: usize,
+ spans: &HashMap<Position, (usize, usize)>,
+ widths: &mut [usize],
+ ) {
+ if spans.is_empty() {
+ return;
+ }
+
+ // The overall width distribution will be different depend on the order.
+ //
+ // We sort spans in order to prioritize the smaller spans first.
+ let mut spans_ordered = spans
+ .iter()
+ .map(|(k, v)| ((k.0, k.1), *v))
+ .collect::<Vec<_>>();
+ spans_ordered.sort_unstable_by(|a, b| match a.1 .0.cmp(&b.1 .0) {
+ Ordering::Equal => a.0.cmp(&b.0),
+ o => o,
+ });
+
+ for ((_, col), (span, width)) in spans_ordered {
+ adjust_column_range(cfg, width, len, col, col + span, widths);
+ }
+ }
+
+ fn adjust_column_range(
+ cfg: &SpannedConfig,
+ max_span_width: usize,
+ len: usize,
+ start: usize,
+ end: usize,
+ widths: &mut [usize],
+ ) {
+ let range_width = range_width(cfg, len, start, end, widths);
+ if range_width >= max_span_width {
+ return;
+ }
+
+ inc_range(widths, max_span_width - range_width, start, end);
+ }
+
+ fn range_width(
+ cfg: &SpannedConfig,
+ len: usize,
+ start: usize,
+ end: usize,
+ widths: &[usize],
+ ) -> usize {
+ let count_borders = count_vertical_borders(cfg, len, start, end);
+ let range_width = widths[start..end].iter().sum::<usize>();
+ count_borders + range_width
+ }
+
+ fn count_vertical_borders(cfg: &SpannedConfig, len: usize, start: usize, end: usize) -> usize {
+ (start..end)
+ .skip(1)
+ .filter(|&i| cfg.has_vertical(i, len))
+ .count()
+ }
+
+ pub(super) fn build_height<T: AsRef<str>>(
+ records: &VecRecords<CellInfo<T>>,
+ cfg: &SpannedConfig,
+ ) -> Vec<usize> {
+ let mut heights = vec![];
+ let mut hspans = HashMap::new();
+
+ for (row, columns) in records.iter_rows().enumerate() {
+ let mut row_height = 0;
+ for (col, cell) in columns.iter().enumerate() {
+ let pos = (row, col);
+ if !cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ let height = cell.count_lines();
+ match cfg.get_row_span(pos) {
+ Some(n) if n > 1 => {
+ let _ = hspans.insert(pos, (n, height));
+ }
+ _ => row_height = max(row_height, height),
+ }
+ }
+
+ heights.push(row_height);
+ }
+
+ adjust_hspans(cfg, heights.len(), &hspans, &mut heights);
+
+ heights
+ }
+
+ pub(super) fn build_width<T: AsRef<str>>(
+ records: &VecRecords<CellInfo<T>>,
+ cfg: &SpannedConfig,
+ ) -> Vec<usize> {
+ let count_columns = records.count_columns();
+
+ let mut widths = vec![0; count_columns];
+ let mut vspans = HashMap::new();
+
+ for (row, columns) in records.iter_rows().enumerate() {
+ for (col, cell) in columns.iter().enumerate() {
+ let pos = (row, col);
+ if !cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ let width = cell.width();
+ match cfg.get_column_span(pos) {
+ Some(n) if n > 1 => {
+ let _ = vspans.insert(pos, (n, width));
+ }
+ _ => widths[col] = max(widths[col], width),
+ }
+ }
+ }
+
+ adjust_vspans(cfg, count_columns, &vspans, &mut widths);
+
+ widths
+ }
+}
diff --git a/vendor/tabled/src/grid/dimension/pool_table_dimension.rs b/vendor/tabled/src/grid/dimension/pool_table_dimension.rs
new file mode 100644
index 000000000..9909c661d
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/pool_table_dimension.rs
@@ -0,0 +1,36 @@
+/// PoolTableDimension is a dimension resolve strategy for [`PoolTable`]
+///
+/// [`PoolTable`]: crate::tables::PoolTable
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+pub struct PoolTableDimension {
+ width: DimensionPriority,
+ height: DimensionPriority,
+}
+
+impl PoolTableDimension {
+ /// Creates a new object.
+ pub fn new(width: DimensionPriority, height: DimensionPriority) -> Self {
+ Self { width, height }
+ }
+
+ /// Return a width priority.
+ pub fn width(&self) -> DimensionPriority {
+ self.width
+ }
+
+ /// Return a height priority.
+ pub fn height(&self) -> DimensionPriority {
+ self.height
+ }
+}
+
+/// A control of width/height logic for situations where we must increase some cell to align columns/row.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum DimensionPriority {
+ /// Increase first cell width/height in a row/column.
+ First,
+ /// Increase last cell width/height in a row/column.
+ Last,
+ /// Increase cells width/height 1 by 1 in a row/column.
+ List,
+}
diff --git a/vendor/tabled/src/grid/dimension/static_dimension.rs b/vendor/tabled/src/grid/dimension/static_dimension.rs
new file mode 100644
index 000000000..f9474f212
--- /dev/null
+++ b/vendor/tabled/src/grid/dimension/static_dimension.rs
@@ -0,0 +1,63 @@
+use crate::grid::dimension::{Dimension, Estimate};
+
+/// A constant dimension.
+#[derive(Debug, Clone)]
+pub struct StaticDimension {
+ width: DimensionValue,
+ height: DimensionValue,
+}
+
+impl StaticDimension {
+ /// Creates a constant dimension.
+ pub fn new(width: DimensionValue, height: DimensionValue) -> Self {
+ Self { width, height }
+ }
+}
+
+impl From<StaticDimension> for (DimensionValue, DimensionValue) {
+ fn from(value: StaticDimension) -> Self {
+ (value.width, value.height)
+ }
+}
+
+impl Dimension for StaticDimension {
+ fn get_width(&self, column: usize) -> usize {
+ self.width.get(column)
+ }
+
+ fn get_height(&self, row: usize) -> usize {
+ self.height.get(row)
+ }
+}
+
+impl<R, C> Estimate<R, C> for StaticDimension {
+ fn estimate(&mut self, _: R, _: &C) {}
+}
+
+/// A dimension value.
+#[derive(Debug, Clone)]
+pub enum DimensionValue {
+ /// Const width value.
+ Exact(usize),
+ /// A list of width values for columns.
+ List(Vec<usize>),
+ /// A list of width values for columns and a value for the rest.
+ Partial(Vec<usize>, usize),
+}
+
+impl DimensionValue {
+ /// Get a width by column.
+ pub fn get(&self, col: usize) -> usize {
+ match self {
+ DimensionValue::Exact(val) => *val,
+ DimensionValue::List(cols) => cols[col],
+ DimensionValue::Partial(cols, val) => {
+ if cols.len() > col {
+ cols[col]
+ } else {
+ *val
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/tabled/src/grid/mod.rs b/vendor/tabled/src/grid/mod.rs
new file mode 100644
index 000000000..cdd8c55c0
--- /dev/null
+++ b/vendor/tabled/src/grid/mod.rs
@@ -0,0 +1,48 @@
+//! Module is responsible for tables underlyign grid.
+//!
+//! It might be used when implementing your own [`TableOption`] and [`CellOption`].
+//!
+//! [`TableOption`]: crate::settings::TableOption
+//! [`CellOption`]: crate::settings::CellOption
+#[cfg(feature = "std")]
+mod colored_config;
+
+mod compact_multiline_config;
+
+pub mod dimension;
+pub mod records;
+
+pub use papergrid::color;
+pub use papergrid::colors;
+pub use papergrid::util;
+
+pub mod config {
+ //! Module contains a list of configs for varios tables/grids.
+
+ pub use papergrid::config::{
+ compact::CompactConfig, AlignmentHorizontal, AlignmentVertical, Border, Borders, Entity,
+ EntityIterator, Indent, Line, Position, Sides,
+ };
+
+ #[cfg(feature = "std")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+ pub use papergrid::config::spanned::{
+ EntityMap, Formatting, HorizontalLine, Offset, SpannedConfig, VerticalLine,
+ };
+
+ #[cfg(feature = "std")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+ pub use super::colored_config::{ColorMap, ColoredConfig};
+
+ pub use super::compact_multiline_config::CompactMultilineConfig;
+}
+
+pub use papergrid::grid::compact::CompactGrid;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use papergrid::grid::iterable::Grid;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use papergrid::grid::peekable::PeekableGrid;
diff --git a/vendor/tabled/src/grid/records/empty_records.rs b/vendor/tabled/src/grid/records/empty_records.rs
new file mode 100644
index 000000000..77ebc812d
--- /dev/null
+++ b/vendor/tabled/src/grid/records/empty_records.rs
@@ -0,0 +1,41 @@
+//! An empty [`Records`] implementation.
+
+use core::iter::{repeat, Repeat, Take};
+
+use super::Records;
+
+/// Empty representation of [`Records`].
+#[derive(Debug, Default, Clone)]
+pub struct EmptyRecords {
+ rows: usize,
+ cols: usize,
+}
+
+impl EmptyRecords {
+ /// Constructs an empty representation of [`Records`] with a given shape.
+ pub fn new(rows: usize, cols: usize) -> Self {
+ Self { rows, cols }
+ }
+}
+
+impl From<(usize, usize)> for EmptyRecords {
+ fn from((count_rows, count_columns): (usize, usize)) -> Self {
+ Self::new(count_rows, count_columns)
+ }
+}
+
+impl Records for EmptyRecords {
+ type Iter = Take<Repeat<Take<Repeat<&'static str>>>>;
+
+ fn iter_rows(self) -> Self::Iter {
+ repeat(repeat("").take(self.cols)).take(self.rows)
+ }
+
+ fn count_columns(&self) -> usize {
+ self.cols
+ }
+
+ fn hint_count_rows(&self) -> Option<usize> {
+ Some(self.rows)
+ }
+}
diff --git a/vendor/tabled/src/grid/records/into_records/buf_records.rs b/vendor/tabled/src/grid/records/into_records/buf_records.rs
new file mode 100644
index 000000000..2db3e45bf
--- /dev/null
+++ b/vendor/tabled/src/grid/records/into_records/buf_records.rs
@@ -0,0 +1,213 @@
+//! A module contains [`BufRows`] and [`BufColumns`] iterators.
+//!
+//! Almoust always they both can be used interchangeably but [`BufRows`] is supposed to be lighter cause it
+//! does not reads columns.
+
+use crate::grid::records::IntoRecords;
+
+use super::either_string::EitherString;
+
+/// BufRecords inspects [`IntoRecords`] iterator and keeps read data buffered.
+/// So it can be checking before hand.
+#[derive(Debug)]
+pub struct BufRows<I, T> {
+ iter: I,
+ buf: Vec<T>,
+}
+
+impl BufRows<(), ()> {
+ /// Creates a new [`BufRows`] structure, filling the buffer.
+ pub fn new<I: IntoRecords>(
+ records: I,
+ sniff: usize,
+ ) -> BufRows<<I::IterRows as IntoIterator>::IntoIter, I::IterColumns> {
+ let mut buf = vec![];
+
+ let mut iter = records.iter_rows().into_iter();
+ for _ in 0..sniff {
+ match iter.next() {
+ Some(row) => buf.push(row),
+ None => break,
+ }
+ }
+
+ BufRows { iter, buf }
+ }
+}
+
+impl<I, T> BufRows<I, T> {
+ /// Returns a slice of a record buffer.
+ pub fn as_slice(&self) -> &[T] {
+ &self.buf
+ }
+}
+
+impl<I, T> From<BufRows<I, T>> for BufColumns<I>
+where
+ T: IntoIterator,
+ T::Item: AsRef<str>,
+{
+ fn from(value: BufRows<I, T>) -> Self {
+ let buf = value
+ .buf
+ .into_iter()
+ .map(|row| row.into_iter().map(|s| s.as_ref().to_string()).collect())
+ .collect();
+
+ BufColumns {
+ iter: value.iter,
+ buf,
+ }
+ }
+}
+
+impl<I, T> IntoRecords for BufRows<I, T>
+where
+ I: Iterator<Item = T>,
+ T: IntoIterator,
+ T::Item: AsRef<str>,
+{
+ type Cell = T::Item;
+ type IterColumns = T;
+ type IterRows = BufRowIter<I, T>;
+
+ fn iter_rows(self) -> Self::IterRows {
+ BufRowIter {
+ buf: self.buf.into_iter(),
+ iter: self.iter,
+ }
+ }
+}
+
+/// Buffered [`Iterator`].
+#[derive(Debug)]
+pub struct BufRowIter<I, T> {
+ buf: std::vec::IntoIter<T>,
+ iter: I,
+}
+
+impl<I, T> Iterator for BufRowIter<I, T>
+where
+ I: Iterator<Item = T>,
+ T: IntoIterator,
+ T::Item: AsRef<str>,
+{
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.buf.next() {
+ Some(i) => Some(i),
+ None => self.iter.next(),
+ }
+ }
+}
+
+/// BufRecords inspects [`IntoRecords`] iterator and keeps read data buffered.
+/// So it can be checking before hand.
+///
+/// In contrast to [`BufRows`] it keeps records by columns.
+#[derive(Debug)]
+pub struct BufColumns<I> {
+ iter: I,
+ buf: Vec<Vec<String>>,
+}
+
+impl BufColumns<()> {
+ /// Creates new [`BufColumns`] structure, filling the buffer.
+ pub fn new<I: IntoRecords>(
+ records: I,
+ sniff: usize,
+ ) -> BufColumns<<I::IterRows as IntoIterator>::IntoIter> {
+ let mut buf = vec![];
+
+ let mut iter = records.iter_rows().into_iter();
+ for _ in 0..sniff {
+ match iter.next() {
+ Some(row) => {
+ let row = row
+ .into_iter()
+ .map(|cell| cell.as_ref().to_string())
+ .collect::<Vec<_>>();
+ buf.push(row)
+ }
+ None => break,
+ }
+ }
+
+ BufColumns { iter, buf }
+ }
+}
+
+impl<I> BufColumns<I> {
+ /// Returns a slice of a keeping buffer.
+ pub fn as_slice(&self) -> &[Vec<String>] {
+ &self.buf
+ }
+}
+
+impl<I> IntoRecords for BufColumns<I>
+where
+ I: Iterator,
+ I::Item: IntoIterator,
+ <I::Item as IntoIterator>::Item: AsRef<str>,
+{
+ type Cell = EitherString<<I::Item as IntoIterator>::Item>;
+ type IterColumns = EitherRowIterator<<I::Item as IntoIterator>::IntoIter>;
+ type IterRows = BufColumnIter<I>;
+
+ fn iter_rows(self) -> Self::IterRows {
+ BufColumnIter {
+ buf: self.buf.into_iter(),
+ iter: self.iter,
+ }
+ }
+}
+
+/// A row iterator for [`BufColumns`]
+#[derive(Debug)]
+pub struct BufColumnIter<I> {
+ buf: std::vec::IntoIter<Vec<String>>,
+ iter: I,
+}
+
+impl<I> Iterator for BufColumnIter<I>
+where
+ I: Iterator,
+ I::Item: IntoIterator,
+ <I::Item as IntoIterator>::Item: AsRef<str>,
+{
+ type Item = EitherRowIterator<<I::Item as IntoIterator>::IntoIter>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.buf.next() {
+ Some(i) => Some(EitherRowIterator::Owned(i.into_iter())),
+ None => self
+ .iter
+ .next()
+ .map(|i| EitherRowIterator::Some(i.into_iter())),
+ }
+ }
+}
+
+/// An iterator over some iterator or allocated buffer.
+#[derive(Debug)]
+pub enum EitherRowIterator<I> {
+ /// Allocated iterator.
+ Owned(std::vec::IntoIter<String>),
+ /// Given iterator.
+ Some(I),
+}
+
+impl<I> Iterator for EitherRowIterator<I>
+where
+ I: Iterator,
+{
+ type Item = EitherString<I::Item>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self {
+ EitherRowIterator::Owned(iter) => iter.next().map(EitherString::Owned),
+ EitherRowIterator::Some(iter) => iter.next().map(EitherString::Some),
+ }
+ }
+}
diff --git a/vendor/tabled/src/grid/records/into_records/either_string.rs b/vendor/tabled/src/grid/records/into_records/either_string.rs
new file mode 100644
index 000000000..f4d97290d
--- /dev/null
+++ b/vendor/tabled/src/grid/records/into_records/either_string.rs
@@ -0,0 +1,22 @@
+//! A module with a utility enum [`EitherString`].
+
+/// Either allocated string or some type which can be used as a string.
+#[derive(Debug)]
+pub enum EitherString<T> {
+ /// Allocated string.
+ Owned(String),
+ /// Something which can be used as a string.
+ Some(T),
+}
+
+impl<T> AsRef<str> for EitherString<T>
+where
+ T: AsRef<str>,
+{
+ fn as_ref(&self) -> &str {
+ match self {
+ EitherString::Owned(s) => s.as_ref(),
+ EitherString::Some(s) => s.as_ref(),
+ }
+ }
+}
diff --git a/vendor/tabled/src/grid/records/into_records/limit_column_records.rs b/vendor/tabled/src/grid/records/into_records/limit_column_records.rs
new file mode 100644
index 000000000..89b2b89ed
--- /dev/null
+++ b/vendor/tabled/src/grid/records/into_records/limit_column_records.rs
@@ -0,0 +1,82 @@
+//! The module contains [`LimitColumns`] records iterator.
+
+use crate::grid::records::IntoRecords;
+
+/// An iterator which limits amount of columns.
+#[derive(Debug)]
+pub struct LimitColumns<I> {
+ records: I,
+ limit: usize,
+}
+
+impl LimitColumns<()> {
+ /// Creates new [`LimitColumns`].
+ pub fn new<I: IntoRecords>(records: I, limit: usize) -> LimitColumns<I> {
+ LimitColumns { records, limit }
+ }
+}
+
+impl<I> IntoRecords for LimitColumns<I>
+where
+ I: IntoRecords,
+{
+ type Cell = I::Cell;
+ type IterColumns = LimitColumnsColumnsIter<<I::IterColumns as IntoIterator>::IntoIter>;
+ type IterRows = LimitColumnsIter<<I::IterRows as IntoIterator>::IntoIter>;
+
+ fn iter_rows(self) -> Self::IterRows {
+ LimitColumnsIter {
+ iter: self.records.iter_rows().into_iter(),
+ limit: self.limit,
+ }
+ }
+}
+
+/// An iterator over rows for [`LimitColumns`].
+#[derive(Debug)]
+pub struct LimitColumnsIter<I> {
+ iter: I,
+ limit: usize,
+}
+
+impl<I> Iterator for LimitColumnsIter<I>
+where
+ I: Iterator,
+ I::Item: IntoIterator,
+ <I::Item as IntoIterator>::Item: AsRef<str>,
+{
+ type Item = LimitColumnsColumnsIter<<I::Item as IntoIterator>::IntoIter>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let iter = self.iter.next()?;
+ Some(LimitColumnsColumnsIter {
+ iter: iter.into_iter(),
+ limit: self.limit,
+ })
+ }
+}
+
+/// An iterator over columns for [`LimitColumns`].
+#[derive(Debug)]
+pub struct LimitColumnsColumnsIter<I> {
+ iter: I,
+ limit: usize,
+}
+
+impl<I> Iterator for LimitColumnsColumnsIter<I>
+where
+ I: Iterator,
+ I::Item: AsRef<str>,
+{
+ type Item = I::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.limit == 0 {
+ return None;
+ }
+
+ self.limit -= 1;
+
+ self.iter.next()
+ }
+}
diff --git a/vendor/tabled/src/grid/records/into_records/limit_row_records.rs b/vendor/tabled/src/grid/records/into_records/limit_row_records.rs
new file mode 100644
index 000000000..a461c6682
--- /dev/null
+++ b/vendor/tabled/src/grid/records/into_records/limit_row_records.rs
@@ -0,0 +1,59 @@
+//! The module contains [`LimitRows`] records iterator.
+
+use crate::grid::records::IntoRecords;
+
+/// [`LimitRows`] is an records iterator which limits amount of rows.
+#[derive(Debug)]
+pub struct LimitRows<I> {
+ records: I,
+ limit: usize,
+}
+
+impl LimitRows<()> {
+ /// Creates new [`LimitRows`] iterator.
+ pub fn new<I: IntoRecords>(records: I, limit: usize) -> LimitRows<I> {
+ LimitRows { records, limit }
+ }
+}
+
+impl<I> IntoRecords for LimitRows<I>
+where
+ I: IntoRecords,
+{
+ type Cell = I::Cell;
+ type IterColumns = I::IterColumns;
+ type IterRows = LimitRowsIter<<I::IterRows as IntoIterator>::IntoIter>;
+
+ fn iter_rows(self) -> Self::IterRows {
+ LimitRowsIter {
+ iter: self.records.iter_rows().into_iter(),
+ limit: self.limit,
+ }
+ }
+}
+
+/// A rows iterator for [`LimitRows`]
+#[derive(Debug)]
+pub struct LimitRowsIter<I> {
+ iter: I,
+ limit: usize,
+}
+
+impl<I> Iterator for LimitRowsIter<I>
+where
+ I: Iterator,
+ I::Item: IntoIterator,
+ <I::Item as IntoIterator>::Item: AsRef<str>,
+{
+ type Item = I::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.limit == 0 {
+ return None;
+ }
+
+ self.limit -= 1;
+
+ self.iter.next()
+ }
+}
diff --git a/vendor/tabled/src/grid/records/into_records/mod.rs b/vendor/tabled/src/grid/records/into_records/mod.rs
new file mode 100644
index 000000000..0a52c41c1
--- /dev/null
+++ b/vendor/tabled/src/grid/records/into_records/mod.rs
@@ -0,0 +1,26 @@
+//! The module contains a list of helpers for [`IntoRecords`]
+//!
+//! [`IntoRecords`]: crate::grid::records::IntoRecords
+
+pub mod limit_column_records;
+pub mod limit_row_records;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub mod buf_records;
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub mod either_string;
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub mod truncate_records;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use buf_records::{BufColumns, BufRows};
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use truncate_records::TruncateContent;
+
+pub use limit_column_records::LimitColumns;
+pub use limit_row_records::LimitRows;
diff --git a/vendor/tabled/src/grid/records/into_records/truncate_records.rs b/vendor/tabled/src/grid/records/into_records/truncate_records.rs
new file mode 100644
index 000000000..17e7e533e
--- /dev/null
+++ b/vendor/tabled/src/grid/records/into_records/truncate_records.rs
@@ -0,0 +1,136 @@
+//! The module contains [`TruncateContent`] records iterator.
+
+use std::borrow::Cow;
+
+use crate::{
+ grid::records::IntoRecords, grid::util::string::string_width_multiline,
+ settings::width::Truncate,
+};
+
+use super::either_string::EitherString;
+
+/// A records iterator which truncates all cells to a given width.
+#[derive(Debug)]
+pub struct TruncateContent<'a, I> {
+ records: I,
+ width: ExactValue<'a>,
+}
+
+impl TruncateContent<'_, ()> {
+ /// Creates new [`TruncateContent`] object.
+ pub fn new<I: IntoRecords>(records: I, width: ExactValue<'_>) -> TruncateContent<'_, I> {
+ TruncateContent { records, width }
+ }
+}
+
+impl<'a, I> IntoRecords for TruncateContent<'a, I>
+where
+ I: IntoRecords,
+{
+ type Cell = EitherString<I::Cell>;
+ type IterColumns = TruncateContentColumnsIter<'a, <I::IterColumns as IntoIterator>::IntoIter>;
+ type IterRows = TruncateContentIter<'a, <I::IterRows as IntoIterator>::IntoIter>;
+
+ fn iter_rows(self) -> Self::IterRows {
+ TruncateContentIter {
+ iter: self.records.iter_rows().into_iter(),
+ width: self.width.clone(),
+ }
+ }
+}
+
+/// A row iterator for [`TruncateContent`].
+#[derive(Debug)]
+pub struct TruncateContentIter<'a, I> {
+ iter: I,
+ width: ExactValue<'a>,
+}
+
+impl<'a, I> Iterator for TruncateContentIter<'a, I>
+where
+ I: Iterator,
+ I::Item: IntoIterator,
+ <I::Item as IntoIterator>::Item: AsRef<str>,
+{
+ type Item = TruncateContentColumnsIter<'a, <I::Item as IntoIterator>::IntoIter>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let iter = self.iter.next()?;
+ Some(TruncateContentColumnsIter {
+ iter: iter.into_iter(),
+ current: 0,
+ width: self.width.clone(),
+ })
+ }
+}
+
+/// A column iterator for [`TruncateContent`].
+#[derive(Debug)]
+pub struct TruncateContentColumnsIter<'a, I> {
+ iter: I,
+ width: ExactValue<'a>,
+ current: usize,
+}
+
+impl<I> Iterator for TruncateContentColumnsIter<'_, I>
+where
+ I: Iterator,
+ I::Item: AsRef<str>,
+{
+ type Item = EitherString<I::Item>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let s = self.iter.next()?;
+
+ let width = self.width.get(self.current);
+ self.current += 1;
+
+ let text_width = string_width_multiline(s.as_ref());
+ if text_width <= width {
+ return Some(EitherString::Some(s));
+ }
+
+ let text = Truncate::truncate_text(s.as_ref(), width);
+ let text = text.into_owned();
+ let text = EitherString::Owned(text);
+
+ Some(text)
+ }
+}
+
+/// A width value.
+#[derive(Debug, Clone)]
+pub enum ExactValue<'a> {
+ /// Const width value.
+ Exact(usize),
+ /// A list of width values for columns.
+ List(Cow<'a, [usize]>),
+}
+
+impl<'a> From<&'a [usize]> for ExactValue<'a> {
+ fn from(value: &'a [usize]) -> Self {
+ Self::List(value.into())
+ }
+}
+
+impl From<Vec<usize>> for ExactValue<'_> {
+ fn from(value: Vec<usize>) -> Self {
+ Self::List(value.into())
+ }
+}
+
+impl From<usize> for ExactValue<'_> {
+ fn from(value: usize) -> Self {
+ Self::Exact(value)
+ }
+}
+
+impl ExactValue<'_> {
+ /// Get a width by column.
+ pub fn get(&self, col: usize) -> usize {
+ match self {
+ ExactValue::Exact(val) => *val,
+ ExactValue::List(cols) => cols[col],
+ }
+ }
+}
diff --git a/vendor/tabled/src/grid/records/mod.rs b/vendor/tabled/src/grid/records/mod.rs
new file mode 100644
index 000000000..494002346
--- /dev/null
+++ b/vendor/tabled/src/grid/records/mod.rs
@@ -0,0 +1,19 @@
+//! The module contains [`Records`], [`ExactRecords`], [`RecordsMut`], [`Resizable`] traits
+//! and its implementations.
+//!
+//! Also it provies a list of helpers for a user built [`Records`] via [`into_records`].
+
+mod empty_records;
+mod records_mut;
+mod resizable;
+
+pub mod into_records;
+
+pub use empty_records::EmptyRecords;
+pub use papergrid::records::{ExactRecords, IntoRecords, IterRecords, PeekableRecords, Records};
+pub use records_mut::RecordsMut;
+pub use resizable::Resizable;
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+pub use papergrid::records::vec_records;
diff --git a/vendor/tabled/src/grid/records/records_mut.rs b/vendor/tabled/src/grid/records/records_mut.rs
new file mode 100644
index 000000000..38c42d2c7
--- /dev/null
+++ b/vendor/tabled/src/grid/records/records_mut.rs
@@ -0,0 +1,34 @@
+use crate::grid::config::Position;
+#[cfg(feature = "std")]
+use crate::grid::records::vec_records::{CellInfo, VecRecords};
+
+/// A [`Records`] representation which can modify cell by (row, column) index.
+///
+/// [`Records`]: crate::grid::records::Records
+pub trait RecordsMut<Text> {
+ /// Sets a text to a given cell by index.
+ fn set(&mut self, pos: Position, text: Text);
+}
+
+impl<T, Text> RecordsMut<Text> for &'_ mut T
+where
+ T: RecordsMut<Text>,
+{
+ fn set(&mut self, pos: Position, text: Text) {
+ T::set(self, pos, text)
+ }
+}
+
+#[cfg(feature = "std")]
+impl RecordsMut<String> for VecRecords<CellInfo<String>> {
+ fn set(&mut self, (row, col): Position, text: String) {
+ self[row][col] = CellInfo::new(text);
+ }
+}
+
+#[cfg(feature = "std")]
+impl RecordsMut<&str> for VecRecords<CellInfo<String>> {
+ fn set(&mut self, (row, col): Position, text: &str) {
+ self[row][col] = CellInfo::new(text.to_string());
+ }
+}
diff --git a/vendor/tabled/src/grid/records/resizable.rs b/vendor/tabled/src/grid/records/resizable.rs
new file mode 100644
index 000000000..29ab38038
--- /dev/null
+++ b/vendor/tabled/src/grid/records/resizable.rs
@@ -0,0 +1,217 @@
+use papergrid::config::Position;
+
+#[cfg(feature = "std")]
+use crate::grid::records::vec_records::VecRecords;
+
+/// A records representation which can be modified by moving rows/columns around.
+pub trait Resizable {
+ /// Swap cells with one another.
+ fn swap(&mut self, lhs: Position, rhs: Position);
+ /// Swap rows with one another.
+ fn swap_row(&mut self, lhs: usize, rhs: usize);
+ /// Swap columns with one another.
+ fn swap_column(&mut self, lhs: usize, rhs: usize);
+ /// Adds a new row to a data set.
+ fn push_row(&mut self);
+ /// Adds a new column to a data set.
+ fn push_column(&mut self);
+ /// Removes a row from a data set by index.
+ fn remove_row(&mut self, row: usize);
+ /// Removes a column from a data set by index.
+ fn remove_column(&mut self, column: usize);
+ /// Inserts a row at index.
+ fn insert_row(&mut self, row: usize);
+ /// Inserts column at index.
+ fn insert_column(&mut self, column: usize);
+}
+
+impl<T> Resizable for &'_ mut T
+where
+ T: Resizable,
+{
+ fn swap(&mut self, lhs: Position, rhs: Position) {
+ T::swap(self, lhs, rhs)
+ }
+
+ fn swap_row(&mut self, lhs: usize, rhs: usize) {
+ T::swap_row(self, lhs, rhs)
+ }
+
+ fn swap_column(&mut self, lhs: usize, rhs: usize) {
+ T::swap_column(self, lhs, rhs)
+ }
+
+ fn push_row(&mut self) {
+ T::push_row(self)
+ }
+
+ fn push_column(&mut self) {
+ T::push_column(self)
+ }
+
+ fn remove_row(&mut self, row: usize) {
+ T::remove_row(self, row)
+ }
+
+ fn remove_column(&mut self, column: usize) {
+ T::remove_column(self, column)
+ }
+
+ fn insert_row(&mut self, row: usize) {
+ T::insert_row(self, row)
+ }
+
+ fn insert_column(&mut self, column: usize) {
+ T::insert_column(self, column)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<T> Resizable for Vec<Vec<T>>
+where
+ T: Default + Clone,
+{
+ fn swap(&mut self, lhs: Position, rhs: Position) {
+ if lhs == rhs {
+ return;
+ }
+
+ let t = std::mem::take(&mut self[lhs.0][lhs.1]);
+ let t = std::mem::replace(&mut self[rhs.0][rhs.1], t);
+ let _ = std::mem::replace(&mut self[lhs.0][lhs.1], t);
+ }
+
+ fn swap_row(&mut self, lhs: usize, rhs: usize) {
+ let t = std::mem::take(&mut self[lhs]);
+ let t = std::mem::replace(&mut self[rhs], t);
+ let _ = std::mem::replace(&mut self[lhs], t);
+ }
+
+ fn swap_column(&mut self, lhs: usize, rhs: usize) {
+ for row in self.iter_mut() {
+ row.swap(lhs, rhs);
+ }
+ }
+
+ fn push_row(&mut self) {
+ let count_columns = self.get(0).map(|l| l.len()).unwrap_or(0);
+ self.push(vec![T::default(); count_columns]);
+ }
+
+ fn push_column(&mut self) {
+ for row in self.iter_mut() {
+ row.push(T::default());
+ }
+ }
+
+ fn remove_row(&mut self, row: usize) {
+ let _ = self.remove(row);
+ }
+
+ fn remove_column(&mut self, column: usize) {
+ for row in self.iter_mut() {
+ let _ = row.remove(column);
+ }
+ }
+
+ fn insert_row(&mut self, row: usize) {
+ let count_columns = self.get(0).map(|l| l.len()).unwrap_or(0);
+ self.insert(row, vec![T::default(); count_columns]);
+ }
+
+ fn insert_column(&mut self, column: usize) {
+ for row in self {
+ row.insert(column, T::default());
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<T> Resizable for VecRecords<T>
+where
+ T: Default + Clone,
+{
+ fn swap(&mut self, lhs: Position, rhs: Position) {
+ if lhs == rhs {
+ return;
+ }
+
+ let t = std::mem::take(&mut self[lhs.0][lhs.1]);
+ let t = std::mem::replace(&mut self[rhs.0][rhs.1], t);
+ let _ = std::mem::replace(&mut self[lhs.0][lhs.1], t);
+ }
+
+ fn swap_row(&mut self, lhs: usize, rhs: usize) {
+ let t = std::mem::take(&mut self[lhs]);
+ let t = std::mem::replace(&mut self[rhs], t);
+ let _ = std::mem::replace(&mut self[lhs], t);
+ }
+
+ fn swap_column(&mut self, lhs: usize, rhs: usize) {
+ for row in self.iter_mut() {
+ row.swap(lhs, rhs);
+ }
+ }
+
+ fn push_row(&mut self) {
+ let records = std::mem::replace(self, VecRecords::new(vec![]));
+ let mut data: Vec<Vec<_>> = records.into();
+
+ let count_columns = data.get(0).map(|l| l.len()).unwrap_or(0);
+ data.push(vec![T::default(); count_columns]);
+
+ *self = VecRecords::new(data);
+ }
+
+ fn push_column(&mut self) {
+ let records = std::mem::replace(self, VecRecords::new(vec![]));
+ let mut data: Vec<Vec<_>> = records.into();
+
+ for row in &mut data {
+ row.push(T::default());
+ }
+
+ *self = VecRecords::new(data);
+ }
+
+ fn remove_row(&mut self, row: usize) {
+ let records = std::mem::replace(self, VecRecords::new(vec![]));
+ let mut data: Vec<Vec<_>> = records.into();
+
+ let _ = data.remove(row);
+
+ *self = VecRecords::new(data);
+ }
+
+ fn remove_column(&mut self, column: usize) {
+ let records = std::mem::replace(self, VecRecords::new(vec![]));
+ let mut data: Vec<Vec<_>> = records.into();
+
+ for row in &mut data {
+ let _ = row.remove(column);
+ }
+
+ *self = VecRecords::new(data);
+ }
+
+ fn insert_row(&mut self, row: usize) {
+ let records = std::mem::replace(self, VecRecords::new(vec![]));
+ let mut data: Vec<Vec<_>> = records.into();
+
+ let count_columns = data.get(0).map(|l| l.len()).unwrap_or(0);
+ data.insert(row, vec![T::default(); count_columns]);
+
+ *self = VecRecords::new(data);
+ }
+
+ fn insert_column(&mut self, column: usize) {
+ let records = std::mem::replace(self, VecRecords::new(vec![]));
+ let mut data: Vec<Vec<_>> = records.into();
+
+ for row in &mut data {
+ row.insert(column, T::default());
+ }
+
+ *self = VecRecords::new(data);
+ }
+}