We could create simple Contract(Conditional / Verified) Types right now.
We just need one Trait Check
:
trait Check<T : Copy> {
fn check(other : T) -> bool;
fn set_raw(&mut self, other : Option<T>);
fn get(&self) -> Option<T>;
fn check2opt(other : T) -> Option<T> {
if Self::check(other) {
Some(other)
} else {
None
}
}
fn check4opt(&self, other : Option<T>) -> bool {
if let Some(val) = other {
Self::check(val)
} else {
false
}
}
fn check42opt(&self, other : Option<T>) -> Option<T> {
if let Some(val) = other {
Self::check2opt(val)
} else {
None
}
}
fn set_valid(&mut self, other : T) {
self.set_raw(Self::check2opt(other));
}
fn set_ifcheck(&mut self, other : T) {
if Self::check(other) {
self.set_raw(Some(other));
}
}
fn upd_valid(&mut self, other : T) {
if self.get().is_some() {
self.set_raw(Self::check2opt(other));
}
}
fn upd_ifcheck(&mut self, other : T) {
if self.get().is_some() && Self::check(other) {
self.set_raw(Some(other));
}
}
fn set4opt_valid(&mut self, other : Option<T>) {
if let Some(val) = other {
self.set_raw(Self::check2opt(val));
} else {
self.set_raw(None);
}
}
fn set4opt_ifcheck(&mut self, other : Option<T>) {
if let Some(val) = other {
if Self::check(val) {
self.set_raw(Some(val));
}
}
}
fn upd4opt_valid(&mut self, other : Option<T>) {
if self.get().is_some() {
if let Some(val) = other {
self.set_raw(Self::check2opt(val));
} else {
self.set_raw(None);
}
}
}
fn upd4opt_ifcheck(&mut self, other : Option<T>) {
if self.get().is_some() {
if let Some(val) = other {
if Self::check(val) {
self.set_raw(Some(val));
}
}
}
}
}
some helpful functions:
fn apply<T, U, F> (fst : U, snd : T, f : F) -> Option<T>
where T : Copy,
U : Check<T>,
F : Fn(T, T) -> T
{
match fst.get() {
Some(t1) => U::check2opt(f (t1, snd)),
_ => None,
}
}
fn apply4opt<T, U, F> (fst : U, snd : Option<T>, f : F) -> Option<T>
where T : Copy,
U : Check<T>,
F : Fn(T, T) -> T
{
match (fst.get(), snd) {
(Some(t1), Some(t2)) => U::check2opt(f (t1, t2)),
_ => None,
}
}
fn apply4check<T, U, F> (fst : U, snd : U, f : F) -> Option<T>
where T : Copy,
U : Check<T>,
F : Fn(T, T) -> T
{
match (fst.get(), snd.get()) {
(Some(t1), Some(t2)) => U::check2opt(f (t1, t2)),
_ => None,
}
}
And we are ready to create any of Contract Types:
#[derive(Debug, Clone, Copy)]
struct PositiveI32(Option<i32>);
impl Check<i32> for PositiveI32 {
fn check(&self, other : i32) -> bool {
other > 0
}
fn set_raw(&mut self, other : Option<i32>) {
self.0 = other;
}
fn get (&self) -> Option<i32> {
self.0
}
}
and we already could use them:
let mut a = PositiveI32(None);
println!("{:?}", a);
// PositiveI32(None)
a.set_ifcheck(15);
println!("{:?}", a);
// PositiveI32(Some(15))
a.set_ifcheck(-5);
println!("{:?}", a);
// PositiveI32(Some(15))
a.set_valid(-35);
println!("{:?}", a);
// PositiveI32(None)
a.upd_ifcheck(45);
println!("{:?}", a);
// PositiveI32(None)
a.set_ifcheck(65);
println!("{:?}", a);
// PositiveI32(Some(65))
let b = *&a;
a.set4opt_ifcheck(apply(b, -6, |x, y| x + y));
println!("{:?}", a);
// PositiveI32(Some(59))