use crate::{Model, Path};
use std::collections::HashSet;
use std::hash::Hash;
use std::sync::{Arc, Mutex};
pub trait CheckerVisitor<M: Model> {
fn visit(&self, model: &M, path: Path<M::State, M::Action>);
}
impl<M, F> CheckerVisitor<M> for F
where M: Model,
F: Fn(Path<M::State, M::Action>),
{
fn visit(&self, _: &M, path: Path<M::State, M::Action>) {
self(path)
}
}
#[allow(clippy::type_complexity)]
pub struct PathRecorder<M: Model>(Arc<Mutex<HashSet<Path<M::State, M::Action>>>>);
impl<M> CheckerVisitor<M> for PathRecorder<M>
where M: Model,
M::Action: Eq + Hash,
M::State: Eq + Hash,
{
fn visit(&self, _: &M, path: Path<M::State, M::Action>) {
self.0.lock().unwrap().insert(path);
}
}
impl<M> PathRecorder<M>
where M: Model,
M::Action: Clone,
M::State: Clone,
{
pub fn new_with_accessor() -> (Self, impl Fn() -> HashSet<Path<M::State, M::Action>>) {
let recorder = Self(Arc::new(Mutex::new(Default::default())));
let accessor = { let r = Arc::clone(&recorder.0); move || r.lock().unwrap().clone() };
(recorder, accessor)
}
}
pub struct StateRecorder<M: Model>(Arc<Mutex<Vec<M::State>>>);
impl<M> CheckerVisitor<M> for StateRecorder<M>
where M: Model,
M::State: Clone,
{
fn visit(&self, _: &M, path: Path<M::State, M::Action>) {
self.0.lock().unwrap().push(path.last_state().clone())
}
}
impl<M> StateRecorder<M>
where M: Model,
M::State: Clone,
{
pub fn new_with_accessor() -> (Self, impl Fn() -> Vec<M::State>) {
let recorder = Self(Arc::new(Mutex::new(Default::default())));
let accessor = { let r = Arc::clone(&recorder.0); move || r.lock().unwrap().clone() };
(recorder, accessor)
}
}