1use crate::console::ConsoleOptions;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct Measurement {
15 pub minimum: usize,
16 pub maximum: usize,
17}
18
19impl Measurement {
20 pub fn new(minimum: usize, maximum: usize) -> Self {
22 Self { minimum, maximum }
23 }
24
25 pub fn with_maximum(self, maximum: usize) -> Self {
27 Self {
28 minimum: self.minimum.min(maximum),
29 maximum: self.maximum.min(maximum),
30 }
31 }
32
33 pub fn with_minimum(self, minimum: usize) -> Self {
35 Self {
36 minimum: self.minimum.max(minimum),
37 maximum: self.maximum.max(minimum),
38 }
39 }
40
41 pub fn shrink(self, amount: usize) -> Self {
43 Self {
44 minimum: self.minimum.saturating_sub(amount),
45 maximum: self.maximum.saturating_sub(amount),
46 }
47 }
48
49 pub fn grow(self, amount: usize) -> Self {
51 Self {
52 minimum: self.minimum + amount,
53 maximum: self.maximum + amount,
54 }
55 }
56
57 pub fn fixed(width: usize) -> Self {
59 Self {
60 minimum: width,
61 maximum: width,
62 }
63 }
64}
65
66pub trait Measurable {
72 fn measure(&self, options: &ConsoleOptions) -> Measurement;
73}
74
75impl Measurable for String {
76 fn measure(&self, _options: &ConsoleOptions) -> Measurement {
77 let w = unicode_width::UnicodeWidthStr::width(self.as_str());
78 Measurement::fixed(w)
79 }
80}
81
82impl Measurable for &str {
83 fn measure(&self, _options: &ConsoleOptions) -> Measurement {
84 let w = unicode_width::UnicodeWidthStr::width(*self);
85 Measurement::fixed(w)
86 }
87}
88
89pub fn measure_renderables<'a>(
94 items: impl IntoIterator<Item = &'a dyn Measurable>,
95 options: &ConsoleOptions,
96) -> Measurement {
97 let mut min = 0usize;
98 let mut max = 0usize;
99 for item in items {
100 let m = item.measure(options);
101 min = min.max(m.minimum);
102 max = max.max(m.maximum);
103 }
104 Measurement::new(min, max)
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_measurement_clamp() {
113 let m = Measurement::new(10, 100).with_maximum(50);
114 assert_eq!(m.minimum, 10);
115 assert_eq!(m.maximum, 50);
116 }
117}