summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2023-11-19 03:15:19 -0500
committerGitHub <noreply@github.com>2023-11-19 03:15:19 -0500
commit5a17212f89b9f4fe6589b9c59137fd4d49903104 (patch)
tree190092486b7471a6bd7ff441a1837fe9000c32c7
parent7c14aa2666a94bd7ec508623b312523620b721ba (diff)
other: add additional clamping functions on numeric types (#1324)
* other: add additional clamping functions on numeric types * add tests and replace one usage
-rw-r--r--src/components/data_table.rs4
-rw-r--r--src/utils/gen_util.rs73
2 files changed, 70 insertions, 7 deletions
diff --git a/src/components/data_table.rs b/src/components/data_table.rs
index 5fb5cb2c..ed79961a 100644
--- a/src/components/data_table.rs
+++ b/src/components/data_table.rs
@@ -21,6 +21,8 @@ pub use data_type::*;
pub mod sortable;
pub use sortable::*;
+use crate::utils::gen_util::ClampExt;
+
/// A [`DataTable`] is a component that displays data in a tabular form.
///
/// Note that [`DataTable`] takes a generic type `S`, bounded by [`SortType`]. This controls whether this table
@@ -120,7 +122,7 @@ impl<DataType: DataToCell<H>, H: ColumnHeader, S: SortType, C: DataTableColumn<H
/// Updates the scroll position to a selected index.
#[allow(clippy::comparison_chain)]
pub fn set_position(&mut self, new_index: usize) {
- let new_index = new_index.clamp(0, self.data.len().saturating_sub(1));
+ let new_index = new_index.clamp_upper(self.data.len().saturating_sub(1));
if self.state.current_index < new_index {
self.state.scroll_direction = ScrollDirection::Down;
} else if self.state.current_index > new_index {
diff --git a/src/utils/gen_util.rs b/src/utils/gen_util.rs
index ae35da8d..cc72c21a 100644
--- a/src/utils/gen_util.rs
+++ b/src/utils/gen_util.rs
@@ -186,6 +186,43 @@ macro_rules! multi_eq_ignore_ascii_case {
};
}
+/// A trait for additional clamping functions on numeric types.
+pub trait ClampExt {
+ /// Restrict a value by a lower bound. If the current value is _lower_ than `lower_bound`,
+ /// it will be set to `_lower_bound`.
+ fn clamp_lower(&self, lower_bound: Self) -> Self;
+
+ /// Restrict a value by an upper bound. If the current value is _greater_ than `upper_bound`,
+ /// it will be set to `upper_bound`.
+ fn clamp_upper(&self, upper_bound: Self) -> Self;
+}
+
+macro_rules! clamp_num_impl {
+ ( $($NumType:ty),+ $(,)? ) => {
+ $(
+ impl ClampExt for $NumType {
+ fn clamp_lower(&self, lower_bound: Self) -> Self {
+ if *self < lower_bound {
+ lower_bound
+ } else {
+ *self
+ }
+ }
+
+ fn clamp_upper(&self, upper_bound: Self) -> Self {
+ if *self > upper_bound {
+ upper_bound
+ } else {
+ *self
+ }
+ }
+ }
+ )*
+ };
+}
+
+clamp_num_impl!(u8, u16, u32, u64, usize);
+
#[cfg(test)]
mod test {
use super::*;
@@ -209,7 +246,7 @@ mod test {
}
#[test]
- fn test_truncate() {
+ fn test_truncate_str() {
let cpu_header = "CPU(c)▲";
assert_eq!(
@@ -232,7 +269,7 @@ mod test {
}
#[test]
- fn test_truncate_cjk() {
+ fn truncate_cjk() {
let cjk = "施氏食獅史";
assert_eq!(
@@ -255,7 +292,7 @@ mod test {
}
#[test]
- fn test_truncate_mixed() {
+ fn truncate_mixed() {
let test = "Test (施氏食獅史) Test";
assert_eq!(
@@ -288,7 +325,7 @@ mod test {
}
#[test]
- fn test_truncate_flags() {
+ fn truncate_flags() {
let flag = "🇨🇦";
assert_eq!(truncate_str(flag, 3_usize), flag);
assert_eq!(truncate_str(flag, 2_usize), flag);
@@ -331,7 +368,7 @@ mod test {
/// This might not be the best way to handle it, but this at least tests that it doesn't crash...
#[test]
- fn test_truncate_hindi() {
+ fn truncate_hindi() {
// cSpell:disable
let test = "हिन्दी";
assert_eq!(truncate_str(test, 10_usize), test);
@@ -346,7 +383,7 @@ mod test {
}
#[test]
- fn test_truncate_emoji() {
+ fn truncate_emoji() {
let heart = "❤️";
assert_eq!(truncate_str(heart, 2_usize), heart);
assert_eq!(truncate_str(heart, 1_usize), heart);
@@ -396,4 +433,28 @@ mod test {
"multi non-matching should fail"
);
}
+
+ #[test]
+ fn test_clamp_upper() {
+ let val: usize = 100;
+ assert_eq!(val.clamp_upper(150), 100);
+
+ let val: usize = 100;
+ assert_eq!(val.clamp_upper(100), 100);
+
+ let val: usize = 100;
+ assert_eq!(val.clamp_upper(50), 50);
+ }
+
+ #[test]
+ fn test_clamp_lower() {
+ let val: usize = 100;
+ assert_eq!(val.clamp_lower(150), 150);
+
+ let val: usize = 100;
+ assert_eq!(val.clamp_lower(100), 100);
+
+ let val: usize = 100;
+ assert_eq!(val.clamp_lower(50), 100);
+ }
}