compare_variables!() { /* proc-macro */ }Expand description
A macro to compare types which implement PartialOrd.
§Overview
This macro performs comparison between two or three values of any type T which
implements PartialOrd and creates a compare_variables::Comparison struct.
If the comparison evaluates to true, the struct is wrapped in Ok,
otherwise in Err to allow easy usage with the ? operator.
The macro syntax is
compare_variables(x _ y)for comparing two values and
compare_variables(x _ y _ z)for comparing three values with _ being any of the comparison operators
<, <=, ==, !=, >, >=.
x, y and z can be either a literal (e.g. 3.141 or 1e10) or a variable:
use compare_variables::compare_variables;
assert!(compare_variables!(2.0 > 1.5).is_ok());
let x = 1;
let y = 2;
assert!(compare_variables!(x < 2 == y).is_ok());
assert!(compare_variables!(x >= 2).is_err());
assert!(compare_variables!(x != y).is_ok());The following example shows how the macro can be combined with ?:
use compare_variables::{compare_variables, Comparison};
fn checked_sub(left: u16, right: u16) -> Result<u16, Comparison<u16>> {
compare_variables!(left >= right)?;
return Ok(left - right);
}
assert_eq!(checked_sub(2, 1).unwrap(), 1);
assert_eq!(checked_sub(2, 2).unwrap(), 0);
assert!(checked_sub(2, 3).is_err());It is also possible to use named and anonymous struct fields as inputs:
use compare_variables::compare_variables;
struct NamedField {
x: f64
}
let n = NamedField {x: 1.0};
assert!(compare_variables!(n.x > -1.0).is_ok());
assert!(compare_variables!(n.x > 1.0).is_err());
struct AnonymousField(i32);
let a = AnonymousField(-5);
assert!(compare_variables!(a.0 > -6).is_ok());
assert!(compare_variables!(a.0 > 1).is_err());§Customizing the message
The keywords val and as allow to customize the treatment of variable names
in the message:
use compare_variables::compare_variables;
// Error message with literals only
let err = compare_variables!(5i32 >= -1i32).unwrap_or_else(|x| x);
assert_eq!(err.to_string(), "`5 >= -1` is true");
let x = 1;
let y = 2;
// Default error message
let err = compare_variables!(x > y).unwrap_or_else(|x| x);
assert_eq!(err.to_string(), "`x (value: 1) > y (value: 2)` is false");
// Rename x in the error message
let err = compare_variables!(x as variable <= y).unwrap_or_else(|x| x);
assert_eq!(err.to_string(), "`variable (value: 1) <= y (value: 2)` is true");
// Only display the underlying value, not the variable name:
let err = compare_variables!(val x > y).unwrap_or_else(|x| x);
assert_eq!(err.to_string(), "`1 > y (value: 2)` is false");
// `as` is ignored if used together with `val`:
let err = compare_variables!(val x as variable > y).unwrap_or_else(|x| x);
assert_eq!(err.to_string(), "`1 > y (value: 2)` is false");§Examples
use compare_variables::compare_variables;
// Different float types:
assert!(compare_variables!(1.5 < 2.0 == 3.0).is_err());
assert!(compare_variables!(1.7f32 == 1.7f32).is_ok());
let f = 2.0;
assert!(compare_variables!(f < 5.2).is_ok());
assert!(compare_variables!(f as f_var == val f).is_ok());
// Signed and unsigned integers
assert!(compare_variables!(1i32 >= 2i32).is_err());
let u = 3usize;
assert!(compare_variables!(2usize < u < 4usize).is_ok());
let i = 15i64;
assert!(compare_variables!(-10i64 <= i).is_ok());
assert!(compare_variables!(-10i64 <= i <= 10i64).is_err());
// Custom types implementing `PartialOrd`.
// Clone and Copy are not required and are only used here to simplify the example.
#[derive(PartialEq, Clone, Copy)]
struct MyFloat64(f64);
impl PartialOrd for MyFloat64 {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
return self.0.partial_cmp(&other.0);
}
}
let myfloat1 = MyFloat64(1.0);
let myfloat2 = MyFloat64(2.0);
assert!(compare_variables!(myfloat1 == myfloat1).is_ok());
assert!(compare_variables!(myfloat1 <= myfloat2).is_ok());
assert!(compare_variables!(myfloat1 >= myfloat2).is_err());