use crate::verification::Contract;
pub struct PrustiStringNonEmpty;
impl Contract for PrustiStringNonEmpty {
type Input = String;
type Output = String;
fn requires(input: &String) -> bool {
!input.is_empty()
}
fn ensures(_input: &String, output: &String) -> bool {
!output.is_empty()
}
fn invariant(&self) -> bool {
true
}
}
pub struct PrustiI32Positive;
impl Contract for PrustiI32Positive {
type Input = i32;
type Output = i32;
fn requires(input: &i32) -> bool {
*input > 0
}
fn ensures(_input: &i32, output: &i32) -> bool {
*output > 0
}
fn invariant(&self) -> bool {
true
}
}
pub struct PrustiBoolValid;
impl Contract for PrustiBoolValid {
type Input = bool;
type Output = bool;
fn requires(_input: &bool) -> bool {
true
}
fn ensures(_input: &bool, _output: &bool) -> bool {
true
}
fn invariant(&self) -> bool {
true
}
}
pub struct PrustiU32NonZero;
impl Contract for PrustiU32NonZero {
type Input = u32;
type Output = u32;
fn requires(input: &u32) -> bool {
*input > 0
}
fn ensures(_input: &u32, output: &u32) -> bool {
*output > 0
}
}
pub struct PrustiU64NonZero;
impl Contract for PrustiU64NonZero {
type Input = u64;
type Output = u64;
fn requires(input: &u64) -> bool {
*input > 0
}
fn ensures(_input: &u64, output: &u64) -> bool {
*output > 0
}
}
pub struct PrustiU128NonZero;
impl Contract for PrustiU128NonZero {
type Input = u128;
type Output = u128;
fn requires(input: &u128) -> bool {
*input > 0
}
fn ensures(_input: &u128, output: &u128) -> bool {
*output > 0
}
}
pub struct PrustiUsizeNonZero;
impl Contract for PrustiUsizeNonZero {
type Input = usize;
type Output = usize;
fn requires(input: &usize) -> bool {
*input > 0
}
fn ensures(_input: &usize, output: &usize) -> bool {
*output > 0
}
}
pub struct PrustiI64Positive;
impl Contract for PrustiI64Positive {
type Input = i64;
type Output = i64;
fn requires(input: &i64) -> bool {
*input > 0
}
fn ensures(_input: &i64, output: &i64) -> bool {
*output > 0
}
}
pub struct PrustiI128Positive;
impl Contract for PrustiI128Positive {
type Input = i128;
type Output = i128;
fn requires(input: &i128) -> bool {
*input > 0
}
fn ensures(_input: &i128, output: &i128) -> bool {
*output > 0
}
}
pub struct PrustiIsizePositive;
impl Contract for PrustiIsizePositive {
type Input = isize;
type Output = isize;
fn requires(input: &isize) -> bool {
*input > 0
}
fn ensures(_input: &isize, output: &isize) -> bool {
*output > 0
}
}
pub struct PrustiF32Finite;
impl Contract for PrustiF32Finite {
type Input = f32;
type Output = f32;
fn requires(input: &f32) -> bool {
input.is_finite()
}
fn ensures(_input: &f32, output: &f32) -> bool {
output.is_finite()
}
}
pub struct PrustiF64Finite;
impl Contract for PrustiF64Finite {
type Input = f64;
type Output = f64;
fn requires(input: &f64) -> bool {
input.is_finite()
}
fn ensures(_input: &f64, output: &f64) -> bool {
output.is_finite()
}
}
pub struct PrustiOptionIsSome<T> {
_phantom: std::marker::PhantomData<T>,
}
impl<T> Default for PrustiOptionIsSome<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> PrustiOptionIsSome<T> {
pub const fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Contract for PrustiOptionIsSome<T>
where
T: crate::traits::Elicitation + Clone + std::fmt::Debug + Send,
{
type Input = Option<T>;
type Output = Option<T>;
fn requires(input: &Option<T>) -> bool {
input.is_some()
}
fn ensures(_input: &Option<T>, output: &Option<T>) -> bool {
output.is_some()
}
}
pub struct PrustiResultIsOk<T, E> {
_phantom: std::marker::PhantomData<(T, E)>,
}
impl<T, E> Default for PrustiResultIsOk<T, E> {
fn default() -> Self {
Self::new()
}
}
impl<T, E> PrustiResultIsOk<T, E> {
pub const fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T, E> Contract for PrustiResultIsOk<T, E>
where
T: crate::traits::Elicitation + Clone + std::fmt::Debug + Send,
E: crate::traits::Elicitation + Clone + std::fmt::Debug + Send,
{
type Input = Result<T, E>;
type Output = Result<T, E>;
fn requires(input: &Result<T, E>) -> bool {
input.is_ok()
}
fn ensures(_input: &Result<T, E>, output: &Result<T, E>) -> bool {
output.is_ok()
}
}
pub struct PrustiVecNonEmpty<T> {
_phantom: std::marker::PhantomData<T>,
}
impl<T> Default for PrustiVecNonEmpty<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> PrustiVecNonEmpty<T> {
pub const fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Contract for PrustiVecNonEmpty<T>
where
T: crate::traits::Elicitation + Clone + std::fmt::Debug + Send,
{
type Input = Vec<T>;
type Output = Vec<T>;
fn requires(input: &Vec<T>) -> bool {
!input.is_empty()
}
fn ensures(_input: &Vec<T>, output: &Vec<T>) -> bool {
!output.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prusti_string_non_empty() {
let input = String::from("hello");
assert!(PrustiStringNonEmpty::requires(&input));
assert!(PrustiStringNonEmpty::ensures(&input, &input));
}
#[test]
fn test_prusti_i32_positive() {
let input = 42i32;
assert!(PrustiI32Positive::requires(&input));
assert!(PrustiI32Positive::ensures(&input, &input));
}
#[test]
fn test_prusti_bool_valid() {
assert!(PrustiBoolValid::requires(&true));
assert!(PrustiBoolValid::requires(&false));
assert!(PrustiBoolValid::ensures(&true, &false));
}
#[test]
fn test_prusti_u32_non_zero() {
assert!(PrustiU32NonZero::requires(&42u32));
assert!(!PrustiU32NonZero::requires(&0u32));
}
#[test]
fn test_prusti_u64_non_zero() {
assert!(PrustiU64NonZero::requires(&42u64));
assert!(!PrustiU64NonZero::requires(&0u64));
}
#[test]
fn test_prusti_u128_non_zero() {
assert!(PrustiU128NonZero::requires(&42u128));
assert!(!PrustiU128NonZero::requires(&0u128));
}
#[test]
fn test_prusti_usize_non_zero() {
assert!(PrustiUsizeNonZero::requires(&42usize));
assert!(!PrustiUsizeNonZero::requires(&0usize));
}
#[test]
fn test_prusti_i64_positive() {
assert!(PrustiI64Positive::requires(&42i64));
assert!(!PrustiI64Positive::requires(&0i64));
}
#[test]
fn test_prusti_i128_positive() {
assert!(PrustiI128Positive::requires(&42i128));
assert!(!PrustiI128Positive::requires(&0i128));
}
#[test]
fn test_prusti_isize_positive() {
assert!(PrustiIsizePositive::requires(&42isize));
assert!(!PrustiIsizePositive::requires(&0isize));
}
#[test]
fn test_prusti_f32_finite() {
assert!(PrustiF32Finite::requires(&42.0f32));
assert!(!PrustiF32Finite::requires(&f32::NAN));
}
#[test]
fn test_prusti_f64_finite() {
assert!(PrustiF64Finite::requires(&42.0f64));
assert!(!PrustiF64Finite::requires(&f64::NAN));
}
#[test]
fn test_prusti_option_is_some() {
let some_val: Option<i32> = Some(42);
let none_val: Option<i32> = None;
assert!(PrustiOptionIsSome::<i32>::requires(&some_val));
assert!(!PrustiOptionIsSome::<i32>::requires(&none_val));
}
#[test]
fn test_prusti_result_is_ok() {
let ok_val: Result<i32, String> = Ok(42);
let err_val: Result<i32, String> = Err("error".to_string());
assert!(PrustiResultIsOk::<i32, String>::requires(&ok_val));
assert!(!PrustiResultIsOk::<i32, String>::requires(&err_val));
}
#[test]
fn test_prusti_vec_non_empty() {
let non_empty: Vec<i32> = vec![1, 2, 3];
let empty: Vec<i32> = vec![];
assert!(PrustiVecNonEmpty::<i32>::requires(&non_empty));
assert!(!PrustiVecNonEmpty::<i32>::requires(&empty));
}
}