tabled/features/
measurment.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! The module contains [`Measurment`] trait and its implementations to be used in [`Height`] and [`Width`].

use papergrid::{
    height::HeightEstimator,
    records::Records,
    width::{CfgWidthFunction, WidthFunc},
    GridConfig,
};

use crate::{height::get_table_total_height, width::get_table_widths_with_total, Height, Width};

/// A width value which can be obtained on behalf of [`Table`].
///
/// [`Table`]: crate::Table
pub trait Measurment<Attribute> {
    /// Returns a measurment value.
    fn measure<R>(&self, records: R, cfg: &GridConfig) -> usize
    where
        R: Records;
}

impl<T> Measurment<T> for usize {
    fn measure<R>(&self, _: R, _: &GridConfig) -> usize {
        *self
    }
}

/// Max width value.
#[derive(Debug)]
pub struct Max;

impl Measurment<Width> for Max {
    fn measure<R>(&self, records: R, cfg: &GridConfig) -> usize
    where
        R: Records,
    {
        let ctrl = CfgWidthFunction::from_cfg(cfg);
        grid_widths(&records, &ctrl)
            .map(|r| r.max().unwrap_or(0))
            .max()
            .unwrap_or(0)
    }
}

impl Measurment<Height> for Max {
    fn measure<R>(&self, records: R, _: &GridConfig) -> usize
    where
        R: Records,
    {
        records_heights(&records)
            .map(|r| r.max().unwrap_or(0))
            .max()
            .unwrap_or(0)
    }
}

/// Min width value.
#[derive(Debug)]
pub struct Min;

impl Measurment<Width> for Min {
    fn measure<R>(&self, records: R, cfg: &GridConfig) -> usize
    where
        R: Records,
    {
        let ctrl = CfgWidthFunction::from_cfg(cfg);
        grid_widths(&records, &ctrl)
            .map(|r| r.min().unwrap_or(0))
            .max()
            .unwrap_or(0)
    }
}

impl Measurment<Height> for Min {
    fn measure<R>(&self, records: R, _: &GridConfig) -> usize
    where
        R: Records,
    {
        records_heights(&records)
            .map(|r| r.max().unwrap_or(0))
            .min()
            .unwrap_or(0)
    }
}

/// Percent from a total table width.
#[derive(Debug)]
pub struct Percent(pub usize);

impl Measurment<Width> for Percent {
    fn measure<R>(&self, records: R, cfg: &GridConfig) -> usize
    where
        R: Records,
    {
        let (_, total) = get_table_widths_with_total(&records, cfg);
        (total * self.0) / 100
    }
}

impl Measurment<Height> for Percent {
    fn measure<R>(&self, records: R, cfg: &GridConfig) -> usize
    where
        R: Records,
    {
        let total = get_table_total_height(&records, cfg, &HeightEstimator::default());
        (total * self.0) / 100
    }
}

fn records_heights<R>(records: &R) -> impl Iterator<Item = impl Iterator<Item = usize> + '_> + '_
where
    R: Records,
{
    (0..records.count_rows()).map(move |row| {
        (0..records.count_columns()).map(move |col| records.count_lines((row, col)))
    })
}

fn grid_widths<'a, R, W>(
    records: &'a R,
    ctrl: &'a W,
) -> impl Iterator<Item = impl Iterator<Item = usize> + 'a> + 'a
where
    W: WidthFunc,
    R: Records,
{
    let (count_rows, count_cols) = (records.count_rows(), records.count_columns());
    (0..count_rows)
        .map(move |row| (0..count_cols).map(move |col| records.get_width((row, col), ctrl)))
}