use std::sync::Mutex;
use cybergraph::{CyberlinkRecord, NeuronId, Particle, Signal, SELF_NETWORK};
pub fn link(
neuron: NeuronId,
from: Particle,
to: Particle,
token: Particle,
amount: u64,
valence: i8,
) -> CyberlinkRecord {
CyberlinkRecord { neuron, from, to, token, amount, valence, height: 0 }
}
pub struct SignalBuilder {
neuron: NeuronId,
links: Vec<CyberlinkRecord>,
}
impl SignalBuilder {
pub fn new(neuron: NeuronId) -> Self {
Self { neuron, links: Vec::new() }
}
pub fn link(
mut self,
from: Particle,
to: Particle,
token: Particle,
amount: u64,
valence: i8,
) -> Self {
self.links.push(link(self.neuron, from, to, token, amount, valence));
self
}
pub fn build(self) -> Signal {
Signal {
neuron: self.neuron,
network: SELF_NETWORK,
links: self.links,
delta_pi: Vec::new(),
box_moves: Vec::new(),
prev: [0u8; 32],
step: 0,
height: 0,
proof: None,
}
}
}
pub struct SignalBus {
inner: Mutex<Vec<Signal>>,
}
impl SignalBus {
pub fn new() -> Self {
Self { inner: Mutex::new(Vec::new()) }
}
pub fn publish(&self, signal: Signal) {
self.inner.lock().expect("signal bus poisoned").push(signal);
}
pub fn drain(&self) -> Vec<Signal> {
let mut guard = self.inner.lock().expect("signal bus poisoned");
std::mem::take(&mut *guard)
}
pub fn is_empty(&self) -> bool {
self.inner.lock().map(|g| g.is_empty()).unwrap_or(true)
}
}
impl Default for SignalBus {
fn default() -> Self { Self::new() }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::chroma::{ChromaId, chroma_particle};
use crate::intent::SUBMIT;
#[test]
fn builder_assembles_signal() {
let neuron: NeuronId = [7u8; 32];
let sig = SignalBuilder::new(neuron)
.link(chroma_particle(ChromaId::Com),
chroma_particle(ChromaId::Spacetime),
SUBMIT, 1, 1)
.build();
assert_eq!(sig.links.len(), 1);
assert_eq!(sig.neuron, neuron);
assert!(sig.proof.is_none());
}
#[test]
fn bus_round_trips_signals() {
let bus = SignalBus::new();
assert!(bus.is_empty());
bus.publish(SignalBuilder::new([0u8; 32]).build());
bus.publish(SignalBuilder::new([0u8; 32]).build());
assert_eq!(bus.drain().len(), 2);
assert!(bus.is_empty());
}
}