310 lines
11 KiB
Rust
310 lines
11 KiB
Rust
#![deny(missing_docs)]
|
|
#![no_std]
|
|
|
|
//! A set of macros similar to the standard library's `assert_*` macros, but return early instead of panicking.
|
|
//! # Example
|
|
//! ```
|
|
//! use soft_assert::*;
|
|
//!
|
|
//! fn not_twenty(x: i32) -> Option<i32> {
|
|
//! // This will return `Option::default()`, which is `None`
|
|
//! soft_assert_ne!(x, 20);
|
|
//! Some(x)
|
|
//! }
|
|
//!
|
|
//! fn double_if_greater_than_5(x: i32) -> i32 {
|
|
//! // But here we don't want to return `i32::default()`,
|
|
//! // so we specify a return value.
|
|
//! soft_assert!(x > 5, x);
|
|
//! x * 2
|
|
//! }
|
|
//!
|
|
//! fn main() {
|
|
//! assert!(not_twenty(10).is_some());
|
|
//! assert!(not_twenty(20).is_none());
|
|
//!
|
|
//! let doubled = double_if_greater_than_5(13);
|
|
//! assert_eq!(doubled, 26);
|
|
//! let not_doubled = double_if_greater_than_5(2);
|
|
//! assert_eq!(not_doubled, 2);
|
|
//! }
|
|
//!
|
|
//! ```
|
|
//!
|
|
//! This crate is `#![no_std]`
|
|
|
|
#[macro_export]
|
|
/// Asserts a condition is true, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`assert`](https://doc.rust-lang.org/std/macro.assert.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_assert!(false, Err(e))`. Ownership of any captured values is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
macro_rules! soft_assert {
|
|
($e:expr) => {
|
|
if !$e {
|
|
return Default::default();
|
|
}
|
|
};
|
|
($e:expr,) => {
|
|
$crate::soft_assert!($e)
|
|
};
|
|
($e:expr, $failed:expr) => {
|
|
if !$e {
|
|
return $failed;
|
|
}
|
|
};
|
|
($e:expr, $failed:expr,) => {
|
|
$crate::soft_assert!($e)
|
|
};
|
|
}
|
|
|
|
/// Asserts two values are equal, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`assert_eq`](https://doc.rust-lang.org/std/macro.assert_eq.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_assert_eq!(1, 2, Err(e))`. Ownership of any captured values is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
#[macro_export]
|
|
macro_rules! soft_assert_eq {
|
|
($x:expr, $y:expr) => {
|
|
if { $x } != { $y } {
|
|
return Default::default();
|
|
}
|
|
};
|
|
($x:expr, $y:expr,) => {
|
|
$crate::soft_assert_eq!($x, $y)
|
|
};
|
|
($x:expr, $y:expr, $failed:expr) => {
|
|
if { $x } != { $y } {
|
|
return $failed;
|
|
}
|
|
};
|
|
($x:expr, $y:expr, $failed:expr,) => {
|
|
$crate::soft_assert_eq!($x, $y, $failed)
|
|
};
|
|
}
|
|
|
|
/// Asserts two values are not equal, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`assert_ne`](https://doc.rust-lang.org/std/macro.assert_ne.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_assert_ne!(2 + 2, 4, Err(e))`. Ownership of any captured values is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
#[macro_export]
|
|
macro_rules! soft_assert_ne {
|
|
($x:expr, $y:expr) => {
|
|
if { $x } == { $y } {
|
|
return Default::default();
|
|
}
|
|
};
|
|
($x:expr, $y:expr,) => {
|
|
$crate::soft_assert_ne!($x, $y)
|
|
};
|
|
($x:expr, $y:expr, $failed:expr) => {
|
|
if { $x } == { $y } {
|
|
return $failed;
|
|
}
|
|
};
|
|
($x:expr, $y:expr, $failed:expr,) => {
|
|
$crate::soft_assert_ne!($x, $y, $failed)
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
/// Asserts a value matches a pattern, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`assert_matches`](https://doc.rust-lang.org/std/assert_matches/macro.assert_matches.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_assert_matches!(x, None, Err(e))`. Ownership of any captured values is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
macro_rules! soft_assert_matches {
|
|
($e:expr, $p:pat) => {
|
|
match $e {
|
|
$p => (),
|
|
_ => return Default::default();
|
|
}
|
|
};
|
|
($e:expr, $p:pat,) => {
|
|
$crate::soft_assert_matches!($x, $y)
|
|
};
|
|
($e:expr, $p:pat, $failed:expr) => {
|
|
match $e {
|
|
$p => (),
|
|
_ => return $failed;
|
|
}
|
|
};
|
|
($e:expr, $p:pat, $failed:expr,) => {
|
|
$crate::soft_assert_matches!($x, $y, $failed)
|
|
};
|
|
}
|
|
|
|
/// If debug assertions are enabled, asserts a condition is true, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_debug_assert!(false, Err(e))`. Ownership of the value is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
#[macro_export]
|
|
macro_rules! soft_debug_assert {
|
|
($e:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert!($e);
|
|
};
|
|
($e:expr,) => {
|
|
$crate::soft_debug_assert!($e);
|
|
};
|
|
($e:expr, $failed:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert!($e, $failed);
|
|
};
|
|
($e:expr, $failed:expr,) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert!($e, $failed);
|
|
};
|
|
}
|
|
|
|
/// If debug assertions are enabled, asserts two values are equal, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`debug_assert_eq`](https://doc.rust-lang.org/std/macro.debug_assert_eq.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_debug_assert_eq!(1, 2, Err(e))`. Ownership of the value is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
#[macro_export]
|
|
macro_rules! soft_debug_assert_eq {
|
|
($x:expr, $y:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert_eq!($x, $y);
|
|
};
|
|
($x:expr, $y:expr,) => {
|
|
$crate::soft_debug_assert_eq!($x, $y);
|
|
};
|
|
($x:expr, $y:expr, $failed:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert_eq!($x, $y, $failed);
|
|
};
|
|
($x:expr, $y:expr, $failed:expr,) => {
|
|
$crate::soft_debug_assert_eq!($x, $y, $failed);
|
|
};
|
|
}
|
|
|
|
/// If debug assertions are enabled, asserts two values are not equal, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`debug_assert_ne`](https://doc.rust-lang.org/std/macro.debug_assert.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_debug_assert_ne!(2 + 2, 4, Err(e))`. Ownership of the value is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
#[macro_export]
|
|
macro_rules! soft_debug_assert_ne {
|
|
($x:expr, $y:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert_ne!($x, $y);
|
|
};
|
|
($x:expr, $y:expr,) => {
|
|
$crate::soft_debug_assert_ne!($x, $y);
|
|
};
|
|
($x:expr, $y:expr, $failed:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert_ne!($x, $y, $failed);
|
|
};
|
|
($x:expr, $y:expr, $failed:expr,) => {
|
|
$crate::soft_debug_assert_ne!($x, $y, $failed);
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
/// Asserts a value matches a pattern, returning otherwise.
|
|
///
|
|
/// Non-panicking version of [`debug_assert_matches`](https://doc.rust-lang.org/std/assert_matches/macro.debug_assert_matches.html).
|
|
///
|
|
/// # Custom return values
|
|
/// Unless otherwise specified, this will return the default value of the return type (if it has one).
|
|
/// A custom value can be returned instead by supplying it as an additional argument (similar to `assert`'s custom message),
|
|
/// i.e. `soft_debug_assert_match!(x, None, Err(e))`. Ownership of any captured values is only taken if the assertion fails, so you can
|
|
/// continue to use them later on.
|
|
///
|
|
/// This does *not* perform `Err(..)`-wrapping, to allow returning any value.
|
|
macro_rules! soft_debug_assert_matches {
|
|
($e:expr, $p:pat) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert_match!($e, $p);
|
|
};
|
|
($e:expr, $p:pat,) => {
|
|
$crate::soft_debug_assert_match!($e, $p);
|
|
};
|
|
($e:expr, $p:pat, $failed:expr) => {
|
|
#[cfg(debug_assertions)]
|
|
$crate::soft_assert_match!($e, $p, $failed);
|
|
};
|
|
($e:expr, $p:pat, $failed:expr,) => {
|
|
$crate::soft_debug_assert_match!($e, $p, $failed);
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test() {
|
|
assert!((|| {
|
|
soft_assert!(true, false);
|
|
true
|
|
})());
|
|
assert!((|| {
|
|
soft_assert!(false, true);
|
|
false
|
|
})());
|
|
assert!((|| {
|
|
soft_assert_eq!((1..=10).sum::<i32>(), 55, false);
|
|
true
|
|
})());
|
|
assert!((|| {
|
|
soft_assert_eq!((1..=10).sum::<i32>(), 3141, true);
|
|
false
|
|
})());
|
|
assert!((|| {
|
|
soft_assert_ne!((1..=10).sum::<i32>(), 3151, false);
|
|
true
|
|
})());
|
|
assert!((|| {
|
|
soft_assert_ne!((1..=10).sum::<i32>(), 55, true);
|
|
false
|
|
})());
|
|
}
|
|
}
|