Skip to main content

zql_cli/db/
format.rs

1use crate::util::painter::Style;
2use std::cmp::max;
3
4#[derive(Clone, Copy, Debug, PartialEq)]
5pub enum Format {
6    Text(usize),
7    Number(usize, usize),
8}
9
10// LongDecimalValue lhs = Text(16)
11// -9999999.9       rhs = Number(8, 2)
12// ----------------
13//       -9999999.9 max = Number(14, 2)
14
15// Dec        lhs = Text(3)
16// -9999999.9 rhs = Number(8, 2)
17// ----------
18// Dec        max = Number(8, 2)
19
20impl Format {
21    pub fn max(lhs: &Self, rhs: &Self) -> Self {
22        match (lhs, rhs) {
23            (Self::Text(lhs), Self::Text(rhs)) => {
24                Self::Text(max(*lhs, *rhs))
25            }
26            (Self::Text(lhs), Self::Number(rhs1, rhs2)) => {
27                let extra = lhs.checked_sub(*rhs1 + *rhs2).unwrap_or_default();
28                Self::Number(rhs1 + extra, *rhs2)
29            }
30            (Self::Number(lhs1, lhs2), Self::Text(rhs)) => {
31                let extra = rhs.checked_sub(lhs1 + lhs2).unwrap_or_default();
32                Self::Number(lhs1 + extra, *lhs2)
33            }
34            (Self::Number(lhs1, lhs2), Self::Number(rhs1, rhs2)) => {
35                Self::Number(max(*lhs1, *rhs1), max(*lhs2, *rhs2))
36            }
37        }
38    }
39
40    pub fn total(&self) -> usize {
41        match self {
42            Self::Text(length) => *length,
43            Self::Number(left, right) => *left + *right,
44        }
45    }
46
47    pub fn left(&self) -> usize {
48        match self {
49            Self::Text(length) => *length,
50            Self::Number(left, _) => *left,
51        }
52    }
53
54    pub fn right(&self) -> usize {
55        match self {
56            Self::Text(_) => 0,
57            Self::Number(_, right) => *right,
58        }
59    }
60
61    pub fn unit(&self) -> Self {
62        match self {
63            Self::Text(_) => Self::Text(1),
64            Self::Number(_, _) => Self::Number(1, 0),
65        }
66    }
67
68    pub fn style(&self) -> Style {
69        match self {
70            Self::Text(_) => Style::Text,
71            Self::Number(_, _) => Style::Number,
72        }
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use crate::db::format::Format;
79    use crate::db::format::Format::{Number, Text};
80    use pretty_assertions::assert_eq;
81
82    #[test]
83    fn test_max_is_generated_from_text_and_text() {
84        assert_eq!(Format::max(&Text(16), &Text(8)), Text(16));
85        assert_eq!(Format::max(&Text(8), &Text(16)), Text(16));
86    }
87
88    #[test]
89    fn test_max_is_generated_from_text_and_number() {
90        assert_eq!(Format::max(&Text(16), &Number(8, 2)), Number(14, 2));
91        assert_eq!(Format::max(&Text(3), &Number(8, 2)), Number(8, 2));
92    }
93
94    #[test]
95    fn test_max_is_generated_from_number_and_text() {
96        assert_eq!(Format::max(&Number(8, 2), &Text(16)), Number(14, 2));
97        assert_eq!(Format::max(&Number(8, 2), &Text(3)), Number(8, 2));
98    }
99
100    #[test]
101    fn test_max_is_generated_from_number_and_number() {
102        assert_eq!(Format::max(&Number(12, 2), &Number(14, 4)), Number(14, 4));
103        assert_eq!(Format::max(&Number(12, 2), &Number(4, 14)), Number(12, 14));
104        assert_eq!(Format::max(&Number(2, 12), &Number(14, 4)), Number(14, 12));
105        assert_eq!(Format::max(&Number(2, 12), &Number(4, 14)), Number(4, 14));
106    }
107
108    #[test]
109    fn test_total_left_and_right_are_generated_from_text() {
110        assert_eq!(Text(16).total(), 16);
111        assert_eq!(Text(16).left(), 16);
112        assert_eq!(Text(16).right(), 0);
113    }
114
115    #[test]
116    fn test_total_left_and_right_are_generated_from_number() {
117        assert_eq!(Number(8, 4).total(), 12);
118        assert_eq!(Number(8, 4).left(), 8);
119        assert_eq!(Number(8, 4).right(), 4);
120    }
121}