tabled/
builder.rs

1//! Builder module provides a [`Builder`] type which helps building
2//! a [`Table`] dynamically.
3//!
4//! It also contains [`IndexBuilder`] which can help to build a table with index.
5//!
6//! # Examples
7//!
8//! Here's an example of [`IndexBuilder`] usage
9//!
10#![cfg_attr(feature = "derive", doc = "```")]
11#![cfg_attr(not(feature = "derive"), doc = "```ignore")]
12//! use tabled::{Table, Tabled, Style};
13//!
14//! #[derive(Tabled)]
15//! struct Mission {
16//!     name: &'static str,
17//!     #[tabled(inline)]
18//!     status: Status,
19//! }
20//!
21//! #[derive(Tabled)]
22//! enum Status {
23//!     Complete,
24//!     Started,
25//!     Ready,
26//!     Unknown,
27//! }
28//!
29//! let data = [
30//!     Mission { name: "Algebra", status: Status::Unknown },
31//!     Mission { name: "Apolo", status: Status::Complete },
32//! ];
33//!
34//! let mut builder = Table::builder(&data).index();
35//! builder
36//!     .set_index(0)
37//!     .set_name(None)
38//!     .transpose();
39//!
40//! let mut table = builder.build();
41//! table.with(Style::modern());
42//!
43//! println!("{}", table);
44//!
45//! assert_eq!(
46//!     table.to_string(),
47//!     concat!(
48//!         "┌──────────┬─────────┬───────┐\n",
49//!         "│          │ Algebra │ Apolo │\n",
50//!         "├──────────┼─────────┼───────┤\n",
51//!         "│ Complete │         │ +     │\n",
52//!         "├──────────┼─────────┼───────┤\n",
53//!         "│ Started  │         │       │\n",
54//!         "├──────────┼─────────┼───────┤\n",
55//!         "│ Ready    │         │       │\n",
56//!         "├──────────┼─────────┼───────┤\n",
57//!         "│ Unknown  │ +       │       │\n",
58//!         "└──────────┴─────────┴───────┘",
59//!    ),
60//! )
61//! ```
62//!
63//! Example when we don't want to show empty data of enum where not all variants are used.
64//!
65#![cfg_attr(feature = "derive", doc = "```")]
66#![cfg_attr(not(feature = "derive"), doc = "```ignore")]
67//! use tabled::{Table, Tabled, Style};
68//!
69//! #[derive(Tabled)]
70//! enum Status {
71//!     #[tabled(inline)]
72//!     Complete {
73//!         started_timestamp: usize,
74//!         finihsed_timestamp: usize,
75//!     },
76//!     #[tabled(inline)]
77//!     Started {
78//!         timestamp: usize,
79//!     },
80//!     Ready,
81//!     Unknown,
82//! }
83//!
84//! let data = [
85//!     Status::Unknown,
86//!     Status::Complete { started_timestamp: 123, finihsed_timestamp: 234 },
87//! ];
88//!
89//! let mut builder = Table::builder(&data);
90//! builder.clean();
91//!
92//! let table = builder.build()
93//!     .with(Style::modern())
94//!     .to_string();
95//!
96//! println!("{}", table);
97//!
98//! assert_eq!(
99//!     table,
100//!     concat!(
101//!         "┌───────────────────┬────────────────────┬─────────┐\n",
102//!         "│ started_timestamp │ finihsed_timestamp │ Unknown │\n",
103//!         "├───────────────────┼────────────────────┼─────────┤\n",
104//!         "│                   │                    │ +       │\n",
105//!         "├───────────────────┼────────────────────┼─────────┤\n",
106//!         "│ 123               │ 234                │         │\n",
107//!         "└───────────────────┴────────────────────┴─────────┘",
108//!    ),
109//! )
110//! ```
111
112use std::{borrow::Cow, iter::FromIterator};
113
114use papergrid::{
115    records::{
116        cell_info::CellInfo,
117        vec_records::{CellMut, VecRecords},
118        Records,
119    },
120    width::{CfgWidthFunction, WidthFunc},
121    AlignmentHorizontal, Entity, Formatting, GridConfig, Indent, Padding,
122};
123
124use crate::{Style, Table};
125
126/// Builder creates a [`Table`] from dynamic data set.
127///
128/// It useful when the amount of columns or rows is not known statically.
129///
130/// ```rust
131/// use tabled::builder::Builder;
132///
133/// let mut builder = Builder::default();
134/// builder.set_columns(["index", "measure", "value"]);
135/// builder.add_record(["0", "weight", "0.443"]);
136///
137/// let table = builder.build();
138///
139/// println!("{}", table);
140/// ```
141///
142/// It may be useful to use [`FromIterator`] for building.
143///
144/// ```rust
145/// use tabled::builder::Builder;
146/// use std::iter::FromIterator;
147///
148/// let data = vec![
149///     ["column1", "column2"],
150///     ["data1", "data2"],
151///     ["data3", "data4"],
152/// ];
153///
154/// let table = Builder::from_iter(data).build();
155///
156/// println!("{}", table);
157/// ```
158#[derive(Debug, Default, Clone)]
159pub struct Builder<'a> {
160    /// A list of rows.
161    records: Vec<Vec<CellInfo<'a>>>,
162    /// A columns row.
163    columns: Option<Vec<CellInfo<'a>>>,
164    /// A number of columns.
165    size: usize,
166    different_column_sizes_used: bool,
167    /// A content of cells which are created in case rows has different length.
168    empty_cell_text: Option<String>,
169}
170
171impl<'a> Builder<'a> {
172    /// Creates a [`Builder`] instance.
173    pub fn new() -> Self {
174        Self::default()
175    }
176
177    /// Set a column size.
178    ///
179    /// If it make it lower then it was originally it is considered NOP.
180    pub fn hint_column_size(&mut self, size: usize) {
181        self.size = size;
182    }
183
184    /// Sets a [`Table`] header.
185    ///
186    /// ```rust
187    /// use tabled::builder::Builder;
188    ///
189    /// let mut builder = Builder::default();
190    /// builder
191    ///     .set_columns((0..3).map(|i| i.to_string()))
192    ///     .add_record(["i", "surname", "lastname"]);
193    /// ```
194    pub fn set_columns<H, T>(&mut self, columns: H) -> &mut Self
195    where
196        H: IntoIterator<Item = T>,
197        T: Into<Cow<'a, str>>,
198    {
199        let ctrl = CfgWidthFunction::new(4);
200        let list = create_row(columns, self.size, &ctrl);
201
202        self.update_size(list.len());
203        self.columns = Some(list);
204
205        self
206    }
207
208    /// Sets off a [`Table`] header.
209    ///
210    /// If not set its a nop.
211    ///
212    /// ```rust
213    /// use tabled::Table;
214    ///
215    /// let data = [("Hello", 1u8, false), ("World", 21u8, true)];
216    ///
217    /// let table = Table::builder(data).build().to_string();
218    ///
219    /// assert_eq!(
220    ///     table,
221    ///     "+-------+----+-------+\n\
222    ///      | &str  | u8 | bool  |\n\
223    ///      +-------+----+-------+\n\
224    ///      | Hello | 1  | false |\n\
225    ///      +-------+----+-------+\n\
226    ///      | World | 21 | true  |\n\
227    ///      +-------+----+-------+"
228    /// );
229    ///
230    ///
231    /// let mut builder = Table::builder(data);
232    /// builder.remove_columns();
233    /// let table = builder.build().to_string();
234    ///
235    /// assert_eq!(
236    ///     table,
237    ///     "+-------+----+-------+\n\
238    ///      | Hello | 1  | false |\n\
239    ///      +-------+----+-------+\n\
240    ///      | World | 21 | true  |\n\
241    ///      +-------+----+-------+"
242    /// );
243    ///
244    /// ```
245    pub fn remove_columns(&mut self) -> &mut Self {
246        self.columns = None;
247        let size = self.get_size();
248        self.size = size;
249
250        self
251    }
252
253    /// Adds a row to a [`Table`].
254    ///
255    /// If [`Self::set_columns`] is not set the first row will be considered a header.
256    ///
257    /// ```rust
258    /// use tabled::builder::Builder;
259    ///
260    /// let mut builder = Builder::default();
261    /// builder.add_record((0..3).map(|i| i.to_string()));
262    /// builder.add_record(["i", "surname", "lastname"]);
263    /// ```
264    pub fn add_record<R, T>(&mut self, row: R) -> &mut Self
265    where
266        R: IntoIterator<Item = T>,
267        T: Into<Cow<'a, str>>,
268    {
269        let ctrl = CfgWidthFunction::new(4);
270        let list = create_row(row, self.size, &ctrl);
271
272        self.update_size(list.len());
273        self.records.push(list);
274
275        self
276    }
277
278    /// Sets a content of cells which are created in case rows has different length.
279    ///
280    ///
281    /// ```rust
282    /// use tabled::builder::Builder;
283    ///
284    /// let mut builder = Builder::default();
285    /// builder.set_default_text("undefined");
286    /// builder.set_columns((0..3).map(|i| i.to_string()));
287    /// builder.add_record(["i"]);
288    /// ```
289    pub fn set_default_text<T>(&mut self, text: T) -> &mut Self
290    where
291        T: Into<String>,
292    {
293        self.empty_cell_text = Some(text.into());
294        self
295    }
296
297    /// Build creates a [`Table`] instance.
298    ///
299    /// ```rust
300    /// use tabled::builder::Builder;
301    ///
302    /// let mut builder = Builder::default();
303    /// builder.set_columns(["i", "column1", "column2"]);
304    /// builder.add_record(["0", "value1", "value2"]);
305    /// ```
306    pub fn build(mut self) -> Table<VecRecords<CellInfo<'a>>> {
307        if self.different_column_sizes_used {
308            self.fix_rows();
309        }
310
311        let has_columns = self.columns.is_some();
312        let records = build_grid(self.records, self.columns, self.size);
313        build_table(records, has_columns)
314    }
315
316    /// Add an index to the [`Table`].
317    ///
318    /// Default index is a range 0-N where N is amount of records.
319    ///
320    /// # Example
321    ///
322    /// ```
323    /// use tabled::Table;
324    ///
325    /// let table = Table::builder(&["Hello", "World", "!"]).index().build();
326    ///
327    /// assert_eq!(
328    ///     table.to_string(),
329    ///     "+---+-------+\n\
330    ///      |   | &str  |\n\
331    ///      +---+-------+\n\
332    ///      | 0 | Hello |\n\
333    ///      +---+-------+\n\
334    ///      | 1 | World |\n\
335    ///      +---+-------+\n\
336    ///      | 2 | !     |\n\
337    ///      +---+-------+"
338    /// )
339    /// ```
340    pub fn index(self) -> IndexBuilder<'a> {
341        IndexBuilder::new(self)
342    }
343
344    /// Clean removes empty columns and rows.
345    ///
346    /// # Example
347    ///
348    /// ```
349    /// use tabled::Table;
350    ///
351    /// let mut builder = Table::builder(&["Hello", "World", ""]);
352    /// builder.clean();
353    ///
354    /// let table = builder.build();
355    ///
356    /// assert_eq!(
357    ///     table.to_string(),
358    ///     "+-------+\n\
359    ///      | &str  |\n\
360    ///      +-------+\n\
361    ///      | Hello |\n\
362    ///      +-------+\n\
363    ///      | World |\n\
364    ///      +-------+"
365    /// )
366    /// ```
367    pub fn clean(&mut self) -> &mut Self {
368        self.clean_columns();
369        self.clean_rows();
370        self
371    }
372
373    /// Creates a Builder from a built [`Records`]
374    ///
375    /// [`Records`]: papergrid::records::Records
376    pub fn custom<R>(records: R) -> CustomRecords<R> {
377        CustomRecords::new(records)
378    }
379
380    fn clean_columns(&mut self) {
381        let mut i = 0;
382        for col in 0..self.size {
383            let col = col - i;
384
385            let mut is_empty = true;
386            for row in 0..self.records.len() {
387                if !self.records[row][col].is_empty() {
388                    is_empty = false;
389                    break;
390                }
391            }
392
393            if is_empty {
394                for row in 0..self.records.len() {
395                    self.records[row].remove(col);
396                }
397
398                if let Some(columns) = self.columns.as_mut() {
399                    if columns.len() > col {
400                        columns.remove(col);
401                    }
402                }
403
404                i += 1;
405            }
406        }
407
408        self.size -= i;
409    }
410
411    fn clean_rows(&mut self) {
412        for row in (0..self.records.len()).rev() {
413            let mut is_empty = true;
414            for col in 0..self.size {
415                if !self.records[row][col].is_empty() {
416                    is_empty = false;
417                    break;
418                }
419            }
420
421            if is_empty {
422                self.records.remove(row);
423            }
424
425            if row == 0 {
426                break;
427            }
428        }
429    }
430
431    fn update_size(&mut self, size: usize) {
432        match size.cmp(&self.size) {
433            std::cmp::Ordering::Less => {
434                if !self.records.is_empty() {
435                    self.different_column_sizes_used = true;
436                }
437            }
438            std::cmp::Ordering::Greater => {
439                self.size = size;
440
441                if !self.records.is_empty() || self.columns.is_some() {
442                    self.different_column_sizes_used = true;
443                }
444            }
445            std::cmp::Ordering::Equal => (),
446        }
447    }
448
449    fn get_size(&mut self) -> usize {
450        let mut max = self.columns.as_ref().map_or(0, Vec::len);
451
452        let max_records = self.records.iter().map(Vec::len).max().unwrap_or(0);
453
454        max = std::cmp::max(max_records, max);
455
456        max
457    }
458
459    fn fix_rows(&mut self) {
460        let ctrl = CfgWidthFunction::new(4);
461        let text = self.empty_cell_text.clone().unwrap_or_default();
462        let empty_cell_text = CellInfo::new(text, &ctrl);
463
464        if let Some(header) = self.columns.as_mut() {
465            if self.size > header.len() {
466                append_vec(header, self.size - header.len(), &empty_cell_text);
467            }
468        }
469
470        for row in &mut self.records {
471            if self.size > row.len() {
472                append_vec(row, self.size - row.len(), &empty_cell_text);
473            }
474        }
475    }
476}
477
478impl<'a, R, V> FromIterator<R> for Builder<'a>
479where
480    R: IntoIterator<Item = V>,
481    V: Into<Cow<'a, str>>,
482{
483    fn from_iter<T: IntoIterator<Item = R>>(iter: T) -> Self {
484        let mut builder = Self::default();
485        for row in iter {
486            builder.add_record(row);
487        }
488
489        builder
490    }
491}
492
493impl<'a, D> Extend<D> for Builder<'a>
494where
495    D: Into<Cow<'a, str>>,
496{
497    fn extend<T: IntoIterator<Item = D>>(&mut self, iter: T) {
498        self.add_record(iter);
499    }
500}
501
502impl From<Vec<Vec<String>>> for Builder<'_> {
503    fn from(strings: Vec<Vec<String>>) -> Self {
504        let size = strings.iter().map(|r| r.len()).max().unwrap_or(0);
505        if size == 0 {
506            return Self::default();
507        }
508
509        let ctrl = CfgWidthFunction::new(4);
510        let mut records = vec![vec![CellInfo::default(); size]; strings.len()];
511        for (row, list) in strings.into_iter().zip(records.iter_mut()) {
512            create_row_exact(list, row, &ctrl);
513        }
514
515        Self {
516            records,
517            size,
518            ..Default::default()
519        }
520    }
521}
522
523impl<'a> From<Vec<Vec<CellInfo<'a>>>> for Builder<'a> {
524    fn from(records: Vec<Vec<CellInfo<'a>>>) -> Self {
525        Self {
526            records,
527            ..Default::default()
528        }
529    }
530}
531
532/// [`IndexBuilder`] helps to add an index to the table.
533///
534/// Index is a column on the left of the table.
535///
536/// It also can be used to transpose the table.
537///
538/// # Example
539///
540/// ```
541/// use tabled::builder::Builder;
542///
543/// let table = Builder::default()
544///     .index()
545///     .build();
546/// ```
547#[derive(Debug, Clone)]
548pub struct IndexBuilder<'a> {
549    /// Index is an index data.
550    /// It's always set.
551    index: Vec<CellInfo<'a>>,
552    /// Name of an index
553    name: Option<CellInfo<'a>>,
554    /// A flag which checks if we need to actually use index.
555    ///
556    /// It might happen when it's only necessary to [Self::transpose] table.
557    print_index: bool,
558    /// A flag which checks if table was transposed.
559    transposed: bool,
560    /// Original builder instance.
561    b: Builder<'a>,
562}
563
564impl<'a> IndexBuilder<'a> {
565    /// Creates a new [`IndexBuilder`] instance.
566    ///
567    /// It creates a default index a range from 0 to N. (N - count rows)
568    /// It also sets a default columns to the range 0 .. N (N - count columns).
569    ///
570    /// # Example
571    ///
572    /// ```
573    /// use tabled::builder::Builder;
574    ///
575    /// let mut builder = Builder::default();
576    /// builder.set_columns(["i", "col-1", "col-2"]);
577    /// builder.add_record(["0", "value-1", "value-2"]);
578    ///
579    /// let table = builder.index().build();
580    ///
581    /// assert_eq!(
582    ///     table.to_string(),
583    ///     "+---+---+---------+---------+\n\
584    ///      |   | i | col-1   | col-2   |\n\
585    ///      +---+---+---------+---------+\n\
586    ///      | 0 | 0 | value-1 | value-2 |\n\
587    ///      +---+---+---------+---------+"
588    /// )
589    /// ```
590    fn new(mut b: Builder<'a>) -> Self {
591        let index = build_range_index(b.records.len());
592
593        if b.columns.is_none() {
594            b.columns = Some(build_range_index(b.size));
595        }
596
597        Self {
598            index,
599            name: None,
600            print_index: true,
601            transposed: false,
602            b,
603        }
604    }
605
606    /// No flag makes builder to not use an index.
607    ///
608    /// It may be useful when only [`Self::transpose`] need to be used.
609    ///
610    /// ```
611    /// use tabled::builder::Builder;
612    ///
613    /// let mut builder = Builder::default();
614    /// builder.set_columns(["i", "col-1", "col-2"]);
615    /// builder.add_record(["0", "value-1", "value-2"]);
616    /// builder.add_record(["2", "value-3", "value-4"]);
617    ///
618    /// let mut builder = builder.index();
619    /// builder.hide_index();
620    ///
621    /// let table = builder.build();
622    ///
623    /// assert_eq!(
624    ///     table.to_string(),
625    ///     "+---+---------+---------+\n\
626    ///      | i | col-1   | col-2   |\n\
627    ///      +---+---------+---------+\n\
628    ///      | 0 | value-1 | value-2 |\n\
629    ///      +---+---------+---------+\n\
630    ///      | 2 | value-3 | value-4 |\n\
631    ///      +---+---------+---------+"
632    /// )
633    /// ```
634    pub fn hide_index(&mut self) -> &mut Self {
635        self.print_index = false;
636        self
637    }
638
639    /// Set an index name.
640    ///
641    /// When [`None`] the name won't be used.
642    pub fn set_name(&mut self, name: Option<String>) -> &mut Self {
643        self.name = name.map(|s| {
644            let ctrl = CfgWidthFunction::new(4);
645            CellInfo::new(s, ctrl)
646        });
647        self
648    }
649
650    /// Sets a index to the chosen column.
651    ///
652    /// Also sets a name of the index to the column name.
653    ///
654    /// # Example
655    ///
656    /// ```
657    /// use tabled::builder::Builder;
658    ///
659    /// let mut builder = Builder::default();
660    /// builder.set_columns(["i", "column1", "column2"]);
661    /// builder.add_record(["0", "value1", "value2"]);
662    ///
663    /// let mut builder = builder.index();
664    /// builder.set_index(1);
665    ///
666    /// let table = builder.build();
667    ///
668    /// assert_eq!(
669    ///     table.to_string(),
670    ///     "+---------+---+---------+\n\
671    ///      |         | i | column2 |\n\
672    ///      +---------+---+---------+\n\
673    ///      | column1 |   |         |\n\
674    ///      +---------+---+---------+\n\
675    ///      | value1  | 0 | value2  |\n\
676    ///      +---------+---+---------+"
677    /// )
678    /// ```
679    pub fn set_index(&mut self, column: usize) -> &mut Self {
680        if self.b.columns.is_none() {
681            return self;
682        }
683
684        if column >= self.b.size {
685            return self;
686        }
687
688        let name = self
689            .b
690            .columns
691            .as_mut()
692            .map(|v| remove_or_default(v, column))
693            .unwrap_or_default();
694
695        self.name = Some(name);
696
697        self.index = get_column(&mut self.b.records, column);
698
699        self.b.size -= 1;
700
701        self
702    }
703
704    /// Transpose index and columns.
705    ///
706    /// # Example
707    ///
708    /// ```
709    /// use tabled::builder::Builder;
710    ///
711    /// let mut builder = Builder::default();
712    /// builder.set_columns(["i", "column-1", "column-2", "column-3"]);
713    /// builder.add_record(["0", "value-1", "value-2", "value-3"]);
714    /// builder.add_record(["1", "value-4", "value-5", "value-6"]);
715    /// builder.add_record(["2", "value-7", "value-8", "value-9"]);
716    ///
717    /// let mut builder = builder.index();
718    /// builder.set_index(1).transpose();
719    ///
720    /// let table = builder.build();
721    ///
722    /// assert_eq!(
723    ///     table.to_string(),
724    ///     "+----------+---------+---------+---------+\n\
725    ///      | column-1 | value-1 | value-4 | value-7 |\n\
726    ///      +----------+---------+---------+---------+\n\
727    ///      | i        | 0       | 1       | 2       |\n\
728    ///      +----------+---------+---------+---------+\n\
729    ///      | column-2 | value-2 | value-5 | value-8 |\n\
730    ///      +----------+---------+---------+---------+\n\
731    ///      | column-3 | value-3 | value-6 | value-9 |\n\
732    ///      +----------+---------+---------+---------+"
733    /// )
734    /// ```
735    pub fn transpose(&mut self) -> &mut Self {
736        let columns = self.b.columns.take().unwrap_or_default();
737
738        let index = std::mem::replace(&mut self.index, columns);
739        self.b.columns = Some(index);
740
741        let new_count_columns = self.b.records.len();
742        make_rows_columns(&mut self.b.records, self.b.size);
743        self.b.size = new_count_columns;
744
745        self.transposed = !self.transposed;
746
747        self
748    }
749
750    /// Builds a table.
751    pub fn build(self) -> Table<VecRecords<CellInfo<'a>>> {
752        Builder::from(self).build()
753    }
754}
755
756impl<'a> From<IndexBuilder<'a>> for Builder<'a> {
757    fn from(index_builder: IndexBuilder<'a>) -> Self {
758        let mut b = build_index(index_builder);
759
760        // fixme: we don't update builder size internally
761        b.fix_rows();
762        b.different_column_sizes_used = false;
763
764        b
765    }
766}
767
768/// A builder which wraps [`Records`] and builds [`Table`] out of it.
769///
770/// [`Records`]: papergrid::records::Records
771#[derive(Debug, Clone)]
772pub struct CustomRecords<R> {
773    records: R,
774    has_header: bool,
775}
776
777impl<R> CustomRecords<R> {
778    fn new(records: R) -> Self {
779        Self {
780            records,
781            has_header: false,
782        }
783    }
784
785    /// Set a flag that custom records has a columns row.
786    pub fn with_header(&mut self) {
787        self.has_header = true;
788    }
789}
790
791impl<R> CustomRecords<R>
792where
793    R: Records,
794{
795    /// Builds a [`Table`] from [`Records`].
796    ///
797    /// [`Records`]: papergrid::records::Records
798    pub fn build(self) -> Table<R> {
799        build_table(self.records, self.has_header)
800    }
801}
802
803fn make_rows_columns(v: &mut Vec<Vec<CellInfo<'_>>>, count_columns: usize) {
804    let mut columns = Vec::with_capacity(count_columns);
805    for _ in 0..count_columns {
806        let column = get_column(v, 0);
807        columns.push(column);
808    }
809
810    v.clear();
811
812    for column in columns {
813        v.push(column);
814    }
815}
816
817fn build_index(mut b: IndexBuilder<'_>) -> Builder<'_> {
818    if b.index.is_empty() {
819        return b.b;
820    }
821
822    let records = &mut b.b.records;
823
824    // it's guaranted to be set
825    let columns = b.b.columns.take().unwrap();
826
827    records.insert(0, columns);
828
829    // add index column
830    if b.print_index {
831        b.b.size += 1;
832        b.index.insert(0, CellInfo::default());
833        insert_column(records, b.index, 0);
834    }
835
836    if let Some(name) = b.name {
837        if b.transposed && b.print_index {
838            records[0][0] = name;
839        } else {
840            records.insert(1, vec![name]);
841        }
842    }
843
844    b.b
845}
846
847fn insert_column<T: Default>(v: &mut [Vec<T>], mut column: Vec<T>, col: usize) {
848    for row in v.iter_mut() {
849        let value = remove_or_default(&mut column, col);
850        row.insert(col, value);
851    }
852}
853
854fn get_column<'a>(v: &mut [Vec<CellInfo<'a>>], col: usize) -> Vec<CellInfo<'a>> {
855    let mut column = Vec::with_capacity(v.len());
856    for row in v.iter_mut() {
857        let value = remove_or_default(row, col);
858        column.push(value);
859    }
860
861    column
862}
863
864fn remove_or_default<T: Default>(v: &mut Vec<T>, i: usize) -> T {
865    if v.len() > i {
866        v.remove(i)
867    } else {
868        T::default()
869    }
870}
871
872fn build_range_index(n: usize) -> Vec<CellInfo<'static>> {
873    let ctrl = CfgWidthFunction::new(4);
874    (0..n)
875        .map(|i| CellInfo::new(i.to_string(), &ctrl))
876        .collect()
877}
878
879fn create_row<'a, R, T, W>(row: R, size: usize, ctrl: &W) -> Vec<CellInfo<'a>>
880where
881    R: IntoIterator<Item = T>,
882    T: Into<Cow<'a, str>>,
883    W: WidthFunc,
884{
885    let mut list = Vec::with_capacity(size);
886    for text in row {
887        list.push(CellInfo::new(text, ctrl))
888    }
889
890    list
891}
892
893fn create_row_exact<'a, R, T, W>(list: &mut [CellInfo<'a>], row: R, ctrl: &W)
894where
895    R: IntoIterator<Item = T>,
896    T: Into<Cow<'a, str>>,
897    W: WidthFunc,
898{
899    for (text, cell) in row.into_iter().zip(list.iter_mut()) {
900        CellMut::set(cell, text, ctrl);
901    }
902}
903
904/// Building [`Table`] from ordinary data.
905fn build_table<R>(records: R, with_header: bool) -> Table<R>
906where
907    R: Records,
908{
909    let mut table = Table::from(records);
910    table.with(Style::ascii());
911
912    configure_grid(table.get_config_mut());
913    table.set_header_flag(with_header);
914
915    table
916}
917
918/// Building [`Grid`] from ordinary data.
919fn build_grid<'a>(
920    mut records: Vec<Vec<CellInfo<'a>>>,
921    columns: Option<Vec<CellInfo<'a>>>,
922    count_columns: usize,
923) -> VecRecords<CellInfo<'a>> {
924    if let Some(columns) = columns {
925        records.insert(0, columns);
926    }
927
928    VecRecords::with_hint(records, count_columns)
929}
930
931fn configure_grid(cfg: &mut GridConfig) {
932    cfg.set_tab_width(4);
933    cfg.set_padding(
934        Entity::Global,
935        Padding {
936            left: Indent::spaced(1),
937            right: Indent::spaced(1),
938            top: Indent::default(),
939            bottom: Indent::default(),
940        },
941    );
942    cfg.set_alignment_horizontal(Entity::Global, AlignmentHorizontal::Left);
943    cfg.set_formatting(
944        Entity::Global,
945        Formatting {
946            horizontal_trim: false,
947            allow_lines_alignement: false,
948            vertical_trim: false,
949        },
950    );
951}
952
953fn append_vec<'a>(v: &mut Vec<CellInfo<'a>>, n: usize, value: &CellInfo<'a>) {
954    v.extend((0..n).map(|_| value.clone()));
955}