use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use super::fabric::Fabric;
use super::neuron::{Firing, FnNeuron, Neuron, NeuronKind};
use super::receptor::Receptor;
use super::signal::{Feature, NeuronId, Payload, Signal};
pub(crate) fn wait_until(f: impl Fn() -> bool) {
let deadline = Instant::now() + Duration::from_secs(10);
while !f() {
assert!(Instant::now() < deadline, "still not true after 10 s");
std::thread::sleep(Duration::from_millis(1));
}
}
pub(crate) fn pass(name: &str) -> impl Neuron {
FnNeuron::reflex(name, |s, _| Firing::one(s)).with_kind(NeuronKind::Receptor)
}
pub(crate) fn fabric_with(neuron: impl Neuron) -> (Fabric, NeuronId) {
let mut b = Fabric::builder();
let r = b.neuron(pass("in"));
let n = b.neuron(neuron);
b.reflex(r, n);
(b.build().unwrap(), r)
}
pub(crate) fn fabric_with_receptor<R: Receptor>(
receptor: R,
) -> (Fabric, NeuronId, Arc<Mutex<Vec<Signal>>>) {
let seen = Arc::new(Mutex::new(Vec::new()));
let mut b = Fabric::builder();
let r = b.receptor(receptor);
let sink = {
let seen = seen.clone();
b.neuron(
FnNeuron::reflex("sink", move |s, _| {
seen.lock().unwrap().push(s);
Firing::Quiet
})
.with_kind(NeuronKind::Effector),
)
};
b.reflex(r, sink);
let fabric = b.build().unwrap();
fabric.start();
(fabric, r, seen)
}
pub(crate) fn command(effector: &str, args: serde_json::Value) -> Signal {
Signal::new(Feature::NONE, Payload::None).command(effector, args)
}