pub fn requires<F, M>(pred: F, message: M) -> Result<()>
where F: Fn() -> bool, M: Display,
Expand description

Checks an arbitrary condition expressed by the given predicate. This is most useful for validating arguments at the start of a function. You must provide an error message, so it often makes sense to call requires once for each argument. This allows for passing more specific error messages back to the caller.

§Examples

Though these example use the crate’s own error type, you can substitute whatever you wish so long as it works.

use runtime_contracts::{requires, error::RuntimeContractError};

fn add_two(i: i32, j: i32) -> Result<i32, RuntimeContractError> {
  requires(|| i > 0, "i must be greater than 0")?;
  requires(|| j > 0, "j must be greater than 0")?;

  Ok(i + j)
}

assert!(add_two(2, 3).is_ok());

The above example seem a bit silly since the usage of i32 could just as easily be changed to u32 to prevent passing in a negative number literal. For example, the following fails to compile:

use runtime_contracts::{requires, error::RuntimeContractError};

fn add_two(i: u32, j: u32) -> Result<u32, RuntimeContractError> {
  requires(|| i > 0, "i must be greater than 0")?;
  requires(|| j > 0, "j must be greater than 0")?;

  Ok(i + j)
}

assert!(add_two(-2, 3).is_ok());

However, what if the number in question is obtained from an external source? In this case, the external source may provide malformed input! For this reason, it is especially useful to use requires to validate input. You can even use the provided combinator on Rust’s Result type to chain contracts into a single statement:

use runtime_contracts::{requires, error::RuntimeContractError};

fn add_two(i: i32, j: i32) -> Result<i32, RuntimeContractError> {
  requires(|| i > 0, "i must be greater than 0")
    .and_then(|_| requires(|| j > 0, "j must be greater than 0"))?;

  Ok(i + j)
}

assert!(add_two(2, 3).is_ok());