use crate::*;
pub fn lens1<'a, O, T, L>(
label: impl ToString,
accessor: L,
inner_fact: impl Fact<'a, T>,
) -> impl Fact<'a, O>
where
O: Target<'a>,
T: Target<'a>,
L: 'a + Clone + Send + Sync + Fn(&mut O) -> &mut T,
{
let accessor2 = accessor.clone();
let getter = move |mut o| accessor(&mut o).clone();
let setter = move |mut o, t: T| {
let r = accessor2(&mut o);
*r = t;
o
};
lens2(label, getter, setter, inner_fact).labeled("lens1")
}
pub fn lens2<'a, O, T>(
label: impl ToString,
getter: impl 'a + Clone + Send + Sync + Fn(O) -> T,
setter: impl 'a + Clone + Send + Sync + Fn(O, T) -> O,
inner_fact: impl Fact<'a, T>,
) -> impl Fact<'a, O>
where
O: Target<'a>,
T: Target<'a>,
{
let label = label.to_string();
lambda("lens", inner_fact, move |g, fact, o: O| {
let t = getter(o.clone());
let t = fact
.mutate(g, t)
.map_check_err(|err| format!("lens1({}) > {}", label, err))?;
Ok(setter(o, t))
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::facts::*;
use arbitrary::*;
#[derive(Debug, Clone, PartialEq, Arbitrary)]
struct S {
x: u32,
y: u32,
}
#[test]
fn test() {
observability::test_run().ok();
let mut g = utils::random_generator();
let f = || vec(lens1("S::x", |s: &mut S| &mut s.x, eq(1)));
let ones = f().build(&mut g);
f().check(&ones).unwrap();
assert!(ones.iter().all(|s| s.x == 1));
}
}