Attribute Macro contract

Source
#[contract]
Expand description

contract is a procedural macro that checks if a given invariant holds true before and after a method call. If the invariant does not hold, the macro will cause the program to panic with a specified message.

§Arguments

  • invariant: A struct method identifier that returns a boolean. This is the invariant that needs to be checked.
  • check_time: An optional string literal that specifies when the invariant should be checked.
    • "require" - The invariant is checked before the operation.
    • "ensure" - The invariant is checked after the operation.
    • "require_and_ensure" - The invariant is checked both before and after the operation.

§Example

use eiffel_macros_gen::contract;
 
struct MyClass {
    // Fields
    a: i32,
};

impl MyClass {
    fn my_invariant(&self) -> bool {
        // Your invariant checks here
        true
    }

    #[contract(my_invariant)]
    fn my_method(&self) {
        // Method body
        println!("Method body {:?}", self.a);
    }

    // Only check the invariant before the method call
    #[contract(my_invariant, "require")]
    fn my_other_method(&self) {
        // Method body
        println!("Method body {:?}", self.a);
    }

    // Only check the invariant after the method call
    #[contract(my_invariant, "ensure")]
    fn my_other_method_after(&self) {
        // Method body
        println!("Method body {:?}", self.a);
    }

    // Only check the invariant before and after (default)
    #[contract(my_invariant, "require_and_ensure")]
    fn my_other_method_before_and_after(&self) {
        // Method body
        println!("Method body {:?}", self.a);
    }

}       

§Test

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_my_method() {
        let my_class = MyClass;
        my_class.my_method(); // This should not panic as the invariant is true
    }
}