Skip to content

Commit

Permalink
other: add additional clamping functions on numeric types (#1324)
Browse files Browse the repository at this point in the history
* other: add additional clamping functions on numeric types

* add tests and replace one usage
  • Loading branch information
ClementTsang authored Nov 19, 2023
1 parent 7c14aa2 commit 5a17212
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 7 deletions.
4 changes: 3 additions & 1 deletion src/components/data_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
73 changes: 67 additions & 6 deletions src/utils/gen_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -209,7 +246,7 @@ mod test {
}

#[test]
fn test_truncate() {
fn test_truncate_str() {
let cpu_header = "CPU(c)▲";

assert_eq!(
Expand All @@ -232,7 +269,7 @@ mod test {
}

#[test]
fn test_truncate_cjk() {
fn truncate_cjk() {
let cjk = "施氏食獅史";

assert_eq!(
Expand All @@ -255,7 +292,7 @@ mod test {
}

#[test]
fn test_truncate_mixed() {
fn truncate_mixed() {
let test = "Test (施氏食獅史) Test";

assert_eq!(
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
}

0 comments on commit 5a17212

Please sign in to comment.