Function runtime_contracts::requires
source · pub fn requires<F, M>(pred: F, message: M) -> Result<()>
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());