tabled/settings/measurement/
mod.rs1use crate::{
4 grid::config::SpannedConfig,
5 grid::dimension::IterGridDimension,
6 grid::records::{ExactRecords, IntoRecords, PeekableRecords, Records},
7 grid::util::string::{self, get_text_width},
8 settings::{Height, Width},
9};
10
11pub trait Measurement<Attribute> {
17 fn measure<R>(&self, records: R, cfg: &SpannedConfig) -> usize
19 where
20 R: Records + ExactRecords + PeekableRecords,
21 <R::Iter as IntoRecords>::Cell: AsRef<str>;
22}
23
24impl<T> Measurement<T> for usize {
25 fn measure<R>(&self, _: R, _: &SpannedConfig) -> usize {
26 *self
27 }
28}
29
30#[derive(Debug)]
32pub struct Max;
33
34impl Measurement<Width> for Max {
35 fn measure<R: Records + ExactRecords + PeekableRecords>(
36 &self,
37 records: R,
38 _: &SpannedConfig,
39 ) -> usize {
40 grid_widths(&records)
41 .map(|r| r.max().unwrap_or(0))
42 .max()
43 .unwrap_or(0)
44 }
45}
46
47impl Measurement<Height> for Max {
48 fn measure<R: Records + ExactRecords + PeekableRecords>(
49 &self,
50 records: R,
51 _: &SpannedConfig,
52 ) -> usize {
53 records_heights(&records)
54 .map(|r| r.max().unwrap_or(0))
55 .max()
56 .unwrap_or(0)
57 }
58}
59
60#[derive(Debug)]
62pub struct Min;
63
64impl Measurement<Width> for Min {
65 fn measure<R: Records + ExactRecords + PeekableRecords>(
66 &self,
67 records: R,
68 _: &SpannedConfig,
69 ) -> usize {
70 grid_widths(&records)
71 .map(|r| r.min().unwrap_or(0))
72 .max()
73 .unwrap_or(0)
74 }
75}
76
77impl Measurement<Height> for Min {
78 fn measure<R: Records + ExactRecords + PeekableRecords>(
79 &self,
80 records: R,
81 _: &SpannedConfig,
82 ) -> usize {
83 records_heights(&records)
84 .map(|r| r.max().unwrap_or(0))
85 .min()
86 .unwrap_or(0)
87 }
88}
89
90#[derive(Debug)]
92pub struct Percent(pub usize);
93
94impl Measurement<Width> for Percent {
95 fn measure<R>(&self, records: R, cfg: &SpannedConfig) -> usize
96 where
97 R: Records,
98 <R::Iter as IntoRecords>::Cell: AsRef<str>,
99 {
100 let total = IterGridDimension::width_total(records, cfg);
101 (total * self.0) / 100
102 }
103}
104
105impl Measurement<Height> for Percent {
106 fn measure<R>(&self, records: R, cfg: &SpannedConfig) -> usize
107 where
108 R: Records + ExactRecords,
109 <R::Iter as IntoRecords>::Cell: AsRef<str>,
110 {
111 let total = IterGridDimension::height_total(records, cfg);
112 (total * self.0) / 100
113 }
114}
115
116fn grid_widths<R>(records: &R) -> impl Iterator<Item = impl Iterator<Item = usize> + '_> + '_
117where
118 R: Records + ExactRecords + PeekableRecords,
119{
120 let (count_rows, count_cols) = (records.count_rows(), records.count_columns());
121 (0..count_rows).map(move |row| {
122 (0..count_cols).map(move |col| get_text_width(records.get_text((row, col).into())))
123 })
124}
125
126fn records_heights<R>(records: &R) -> impl Iterator<Item = impl Iterator<Item = usize> + '_> + '_
127where
128 R: Records + ExactRecords + PeekableRecords,
129{
130 (0..records.count_rows()).map(move |row| {
131 (0..records.count_columns())
132 .map(move |col| string::count_lines(records.get_text((row, col).into())))
133 })
134}