Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

other: add additional clamping functions on numeric types #1324

Merged
merged 2 commits into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}