Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Introduce DefensiveMin and DefensiveMax #12554

Merged
142 changes: 142 additions & 0 deletions frame/support/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,92 @@ where
}
}

/// Defensively checks the minimum between two values.
pub trait DefensiveMin<T> {
/// Defensively checks the minimum between two values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please wrap lines at 100 as noted in format guides, not less.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. done.

/// or if the two values are the same.
///
/// # Example
///
/// assert_eq!(10, 10_u32.defensive_min(10_u32));
/// ```
fn defensive_min(&self, t: T) -> Self;
/// Strictly defensively checks the minimum between two values.
///
/// # Example
///
/// assert_eq!(10, 10_u32.defensive_strict_min(11_u32));
/// ```
fn defensive_strict_min(&self, t: T) -> Self;
}

impl<T, U> DefensiveMin<U> for T
where
T: Clone + sp_std::cmp::PartialOrd<U>,
U: Copy + std::fmt::Debug,
dharjeezy marked this conversation as resolved.
Show resolved Hide resolved
{
fn defensive_min(&self, u: U) -> Self {
if self <= &u {
self.clone()
} else {
defensive!("DefensiveMin minimize");
self.clone()
}
}

fn defensive_strict_min(&self, u: U) -> Self {
if self < &u {
self.clone()
} else {
defensive!("DefensiveStrictMin minimize");
self.clone()
}
}
}

/// Defensively checks the maximum between two values.
pub trait DefensiveMax<T> {
/// Defensively checks the maximum between two values
/// or if the two values are the same.
///
/// # Example
///
/// assert_eq!(10, 10_u32.defensive_max(10_u32));
/// ```
fn defensive_max(&self, t: T) -> Self;
/// Strictly defensively checks the minimum between two values.
///
/// # Example
///
/// assert_eq!(11, 11_u32.defensive_strict_max(10_u32));
/// ```
fn defensive_strict_max(&self, t: T) -> Self;
}

impl<T, U> DefensiveMax<U> for T
where
T: Clone + sp_std::cmp::PartialOrd<U>,
U: Copy + std::fmt::Debug,
{
fn defensive_max(&self, u: U) -> Self {
if self >= &u {
self.clone()
} else {
defensive!("DefensiveMax maximize");
self.clone()
}
}

fn defensive_strict_max(&self, u: U) -> Self {
if self > &u {
self.clone()
} else {
defensive!("DefensiveStrictMax maximize");
self.clone()
}
}
}

/// Anything that can have a `::len()` method.
pub trait Len {
/// Return the length of data type.
Expand Down Expand Up @@ -1109,4 +1195,60 @@ mod test {
let data = decoded.encode();
WrapperOpaque::<u32>::decode(&mut &data[..]).unwrap();
}

#[test]
fn defensive_min_works() {
assert_eq!(10, 10_u32.defensive_min(11_u32));
assert_eq!(10, 10_u32.defensive_min(10_u32));
}

#[test]
#[should_panic(expected = "Defensive failure has been triggered!: \"DefensiveMin minimize\"")]
fn defensive_min_panics() {
assert_eq!(9, 12_u32.defensive_min(9_u32));
assert_eq!(10, 11_u32.defensive_min(10_u32));
}

#[test]
fn defensive_strict_min_works() {
assert_eq!(10, 10_u32.defensive_strict_min(11_u32));
assert_eq!(9, 9_u32.defensive_strict_min(10_u32));
}

#[test]
#[should_panic(
expected = "Defensive failure has been triggered!: \"DefensiveStrictMin minimize\""
)]
fn defensive_strict_min_panics() {
assert_eq!(9, 9_u32.defensive_strict_min(9_u32));
assert_eq!(10, 11_u32.defensive_strict_min(10_u32));
}

#[test]
fn defensive_max_works() {
assert_eq!(11, 11_u32.defensive_max(10_u32));
assert_eq!(10, 10_u32.defensive_max(10_u32));
}

#[test]
#[should_panic(expected = "Defensive failure has been triggered!: \"DefensiveMax maximize\"")]
fn defensive_max_panics() {
assert_eq!(12, 9_u32.defensive_max(12_u32));
assert_eq!(11, 10_u32.defensive_max(11_u32));
}

#[test]
fn defensive_strict_max_works() {
assert_eq!(11, 11_u32.defensive_strict_max(10_u32));
assert_eq!(10, 10_u32.defensive_strict_max(9_u32));
}

#[test]
#[should_panic(
expected = "Defensive failure has been triggered!: \"DefensiveStrictMax maximize\""
)]
fn defensive_strict_max_panics() {
assert_eq!(9, 9_u32.defensive_strict_max(9_u32));
assert_eq!(11, 10_u32.defensive_strict_max(11_u32));
}
}