Skip to content

Commit

Permalink
Merge pull request #4 from EmbarkStudios/ensure
Browse files Browse the repository at this point in the history
Add ensure macro
  • Loading branch information
dtolnay authored Oct 7, 2019
2 parents dcb6b79 + a1306a2 commit abcb255
Showing 1 changed file with 97 additions and 0 deletions.
97 changes: 97 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,78 @@ macro_rules! bail {
};
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !condition { return Err(From::from($err)) }`.
///
/// Similar to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`,
/// it does not panic.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// #
/// # fn main() -> Result<()> {
/// # let user = 0;
/// # let resource = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// # Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use std::fmt::{self, Display};
/// #
/// # #[derive(Debug)]
/// # enum ScienceError {
/// # RecursionLimitExceeded,
/// # }
/// #
/// # impl std::error::Error for ScienceError {}
/// #
/// # impl Display for ScienceError {
/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// # unimplemented!()
/// # }
/// # }
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// # const IGNORE: &str = stringify! {
/// #[derive(Error, Debug)]
/// enum ScienceError {
/// #[error(display = "recursion limit exceeded")]
/// RecursionLimitExceeded,
/// ...
/// }
/// # };
///
/// # fn main() -> Result<()> {
/// # let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// # Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
($cond:expr, $err:expr $(,)?) => {
if !($cond) {
return std::result::Result::Err($crate::anyhow!($err));
}
};
($cond:expr, $fmt:expr, $($arg:tt)*) => {
if !($cond) {
return std::result::Result::Err($crate::anyhow!($fmt, $($arg)*));
}
};
}

/// Construct an ad-hoc error from a string.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
Expand Down Expand Up @@ -348,3 +420,28 @@ pub mod private {
Error::new_adhoc(message, backtrace)
}
}

#[cfg(test)]
mod test {
#[test]
fn ensure() {
let f = || {
ensure!(1 + 1 == 2, "This is correct");
Ok(())
};
assert!(f().is_ok());

let v = 1;
let f = || {
ensure!(v + v == 2, "This is correct, v: {}", v);
Ok(())
};
assert!(f().is_ok());

let f = || {
ensure!(v + v == 1, "This is not correct, v: {}", v);
Ok(())
};
assert!(f().is_err());
}
}

0 comments on commit abcb255

Please sign in to comment.