|
1 |
| -use std::collections::{BTreeMap, BTreeSet}; |
2 |
| - |
3 |
| -use egui::Color32; |
| 1 | +use egui::{Color32, WidgetText}; |
| 2 | +use std::{ |
| 3 | + collections::{BTreeMap, BTreeSet}, |
| 4 | + fmt::Display, |
| 5 | +}; |
4 | 6 |
|
5 | 7 | #[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq)]
|
6 | 8 | #[serde(default)] // if we add new fields, give them default values when deserializing old state
|
@@ -65,48 +67,72 @@ pub struct RowSizeConfig {
|
65 | 67 | pub units: SizeUnits,
|
66 | 68 | }
|
67 | 69 |
|
68 |
| -#[derive(Default, serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq)] |
| 70 | +#[derive(Default, serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq, Clone, Copy)] |
69 | 71 | pub enum SizeUnits {
|
70 | 72 | Bytes,
|
71 | 73 | KB,
|
72 | 74 | MB,
|
73 | 75 | GB,
|
74 | 76 | TB,
|
75 | 77 | #[default]
|
76 |
| - /// Is output as a String because it includes the unit and is the largest unit where the output value is >= 1 |
77 | 78 | Auto,
|
78 | 79 | }
|
| 80 | + |
79 | 81 | impl SizeUnits {
|
80 |
| - pub(crate) fn convert(&self, row_size_in_bytes: usize) -> serde_json::Value { |
81 |
| - let scalar = match self { |
| 82 | + fn to_concrete(self, row_size_in_bytes: usize) -> Self { |
| 83 | + if !matches!(self, Self::Auto) { |
| 84 | + // Easy case where type is specified |
| 85 | + return self; |
| 86 | + } |
| 87 | + |
| 88 | + // Determine which unit to use when using auto |
| 89 | + let units = [Self::Bytes, Self::KB, Self::MB, Self::GB, Self::TB]; |
| 90 | + let mut last_index = 0; |
| 91 | + let row_size_in_bytes = row_size_in_bytes as f64; |
| 92 | + for (i, unit) in units.iter().enumerate().skip(1) { |
| 93 | + if (row_size_in_bytes / unit.scalar()) >= 1.0 { |
| 94 | + last_index = i; |
| 95 | + } else { |
| 96 | + // Last was as correct unit |
| 97 | + break; |
| 98 | + } |
| 99 | + } |
| 100 | + units[last_index] |
| 101 | + } |
| 102 | + |
| 103 | + /// Returns the scalar for that unit |
| 104 | + /// |
| 105 | + /// Panics: if unit is [`Self::Auto`] |
| 106 | + fn scalar(&self) -> f64 { |
| 107 | + match self { |
82 | 108 | SizeUnits::Bytes => 1.0,
|
83 | 109 | SizeUnits::KB => 1024.0,
|
84 | 110 | SizeUnits::MB => 1024.0 * 1024.0,
|
85 | 111 | SizeUnits::GB => 1024.0 * 1024.0 * 1024.0,
|
86 | 112 | SizeUnits::TB => 1024.0 * 1024.0 * 1024.0 * 1024.0,
|
87 | 113 | SizeUnits::Auto => {
|
88 |
| - // TODO 5: Rewrite with shifts for performance |
89 |
| - // Special handling see doc string for explanation |
90 |
| - let units = ["Bytes", "KB", "MB", "GB", "TB"]; |
91 |
| - let mut last_index = 0; |
92 |
| - let mut scalar = 1.0f64; |
93 |
| - let row_size_in_bytes = row_size_in_bytes as f64; |
94 |
| - for i in 1..units.len() { |
95 |
| - let new_scalar = scalar * 1024.0; |
96 |
| - if (row_size_in_bytes / new_scalar) >= 1.0 { |
97 |
| - last_index = i; |
98 |
| - scalar = new_scalar; |
99 |
| - } else { |
100 |
| - // Last was as correct unit |
101 |
| - break; |
102 |
| - } |
103 |
| - } |
104 |
| - let result = row_size_in_bytes / scalar; |
105 |
| - return format!("{result:0>9.4} {}", units[last_index]).into(); |
| 114 | + unreachable!("precondition violated: Auto does not have a scalar") |
106 | 115 | }
|
107 |
| - }; |
| 116 | + } |
| 117 | + } |
| 118 | + |
| 119 | + /// Output as a string because includes the unit |
| 120 | + pub(crate) fn convert(&self, row_size_in_bytes: usize) -> serde_json::Value { |
| 121 | + let concrete_unit = self.to_concrete(row_size_in_bytes); |
| 122 | + let scalar = concrete_unit.scalar(); |
108 | 123 | let result = row_size_in_bytes as f64 / scalar;
|
109 |
| - result.into() |
| 124 | + format!("{result:0>9.4} {concrete_unit}").into() |
| 125 | + } |
| 126 | + |
| 127 | + pub fn as_str(&self) -> &'static str { |
| 128 | + match self { |
| 129 | + SizeUnits::Bytes => "Bytes", |
| 130 | + SizeUnits::KB => "KB", |
| 131 | + SizeUnits::MB => "MB", |
| 132 | + SizeUnits::GB => "GB", |
| 133 | + SizeUnits::TB => "TB", |
| 134 | + SizeUnits::Auto => "Auto", |
| 135 | + } |
110 | 136 | }
|
111 | 137 | }
|
112 | 138 |
|
@@ -222,3 +248,15 @@ impl Default for LevelConversion {
|
222 | 248 | }
|
223 | 249 | }
|
224 | 250 | }
|
| 251 | + |
| 252 | +impl Display for SizeUnits { |
| 253 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 254 | + write!(f, "{}", self.as_str()) |
| 255 | + } |
| 256 | +} |
| 257 | + |
| 258 | +impl From<SizeUnits> for WidgetText { |
| 259 | + fn from(value: SizeUnits) -> Self { |
| 260 | + value.as_str().into() |
| 261 | + } |
| 262 | +} |
0 commit comments