#![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 { //! // 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::(), 55, false); true })()); assert!((|| { soft_assert_eq!((1..=10).sum::(), 3141, true); false })()); assert!((|| { soft_assert_ne!((1..=10).sum::(), 3151, false); true })()); assert!((|| { soft_assert_ne!((1..=10).sum::(), 55, true); false })()); } }