# Adhesion
[![Linux build status](https://travis-ci.org/ErichDonGubler/adhesion-rs.svg)](https://travis-ci.org/ErichDonGubler/adhesion-rs)
[![Windows build status](https://ci.appveyor.com/api/projects/status/github/ErichDonGubler/adhesion-rs?svg=true)](https://ci.appveyor.com/project/ErichDonGubler/adhesion-rs)
[![crates.io latest published version](https://img.shields.io/crates/v/adhesion.svg)](https://crates.io/crates/adhesion)
[![docs.rs latest published version](https://docs.rs/adhesion/badge.svg)](https://docs.rs/adhesion)
A set of macros for [design by contact](https://en.wikipedia.org/wiki/Design_by_contract)
in Rust. The design of this library was inspired by [D's contract programming
facilities](https://tour.dlang.org/tour/en/gems/contract-programming).
Here's a quick example:
```rust,skt-main
use std::i32;
contract! {
fn add_one_to_odd(x: i32) -> i32 {
post(y) {
assert!(y - 1 == x, "reverse operation did not produce input");
}
body {
x + 1
}
pre {
assert!(x != i32::MAX, "cannot add one to input at max of number range");
assert!(x % 2 != 0, "evens ain't appropriate here");
}
}
}
assert!(add_one_to_odd(3) == 4);
assert!(add_one_to_odd(5) == 6);
assert_that!(add_one_to_odd(2), panics);
assert_that!(add_one_to_odd(i32::MAX), panics);
```
In the above example, `pre` runs before `body`, and `post`, which has the
return value of this function bound to `y`, runs after. We can also define
checks with the `double_check` block, which will be checked before **and**
after `body` has run:
```rust,should_panic,skt-main
struct Counter {
count: u32,
max: u32
}
contract! {
fn increment_counter(c: &mut Counter) {
double_check {
assert!(c.count <= c.max, "counter max has been exceeded");
}
body {
c.count += 1;
}
}
}
let mut counter = Counter { count: 0, max: 3 };
macro_rules! assert_incremented_eq {
($e: expr) => ({
increment_counter(&mut counter);
assert!(counter.count == $e, format!("expected counter to be {}, got {}", $e, counter.count));
})
}
assert_incremented_eq!(1);
assert_incremented_eq!(2);
assert_incremented_eq!(3);
assert_incremented_eq!(4); // panics!
```
Actually, the above example can use a top-level `double_check` block inside of
an `impl` block instead, so that invariants can be maintained for each method
without needing to duplicate code:
```rust,should_panic,skt-main
struct Counter {
count: u32,
max: u32
}
impl Counter {
contract! {
double_check {
assert!(self.count <= self.max, "counter max has been exceeded");
}
fn increment(&mut self) {
body {
self.count.checked_add();
}
}
}
}
let mut counter = Counter { count: 0, max: 3 };
macro_rules! assert_incremented_eq {
($e: expr) => ({
counter.increment();
assert!(counter.count == $e, format!("expected counter to be {}, got {}", $e, counter.count));
})
}
assert_incremented_eq!(1);
assert_incremented_eq!(2);
assert_incremented_eq!(3);
assert_incremented_eq!(4); // panics!
```
Nifty, right? Check out [the docs](https://docs.rs/adhesion) if you want more
detail about this crate and what you can do with it.
## FAQ
### Why "Adhesion"?
This library is called "Adhesion" in reference to a particular type of contract
called a "contract of adhesion", also known as a "take-it-or-leave-it"
contract. Assertions in programming are definitely "take it or leave it" -- if
an assertion is failing, you either have to fix the conditions of the
assertion, or change the assertion itself. It sounded appropriate!
### Why has D's `invariant` been renamed to `double_check`?
After the v0.2.0 release, @eternaleye pointed out in this [Reddit thread](https://www.reddit.com/r/rust/comments/6ooinu/adhesionrs_v020_contract_programming_in_rust_with/dkjd3kc/)
that technically an "invariant" connotes a strong guarantee that must be
rigorously maintained between ALL operations in code. This sort of guarantee is
NOT provided by the behavior D's `invariant` block, as demonstrated by [the
link](http://hackingdistributed.com/2016/07/13/reentrancy-woes/) that
@eternaleye provided.
Semantics are important, especially in systems that attempt to introduce more
rigor to software development like design by contract. For this reason, the
combined pre- and post-check block that D calls `invariant` is called
`double_check` in this library.
## Licensing
This project is dual-licensed under your choice of the [MIT license](/LICENSE-MIT)
or the [Apache 2.0 license](/LICENSE-APACHE-2.0).
* Adhesion uses a modified version of components from the [rust-parse-generics](https://github.com/DanielKeep/rust-parse-generics)
project. Both the original and modified versions here use the same dual
license as this project.
## Contributors
* @ErichDonGubler, original author
* @dzamlo, for providing assistance with various important features.
* @DanielKeep, for his incredible help making it possible for generics to be
parsed and used in macros generally, and for his mentoring during
Adhesion's development of its features involving generics.
* @eternaleye, for bringing some security expertise to bear and motivating
the `double_check` divergence from D's `invariant`.