diff options
Diffstat (limited to 'src/actor.rs')
-rw-r--r-- | src/actor.rs | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/src/actor.rs b/src/actor.rs index 3b03fa6..e83c003 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -1,4 +1,14 @@ +use std::collections::HashMap; +use std::sync::mpsc::{Receiver, Sender}; +use std::thread; + +use uuid::Uuid; + use crate::number::Number; +use crate::world::World; + +#[derive(Clone, Hash, Copy, Eq, PartialEq)] +pub struct ActorId(Uuid); #[derive(Clone)] pub enum Type { @@ -18,12 +28,91 @@ pub enum Type { } #[derive(Clone)] +pub enum Value { + String(String), + Record(Vec<(String, Value)>), + Number(Number), + List(Vec<Value>), +} + +#[derive(Clone)] pub struct Slot { pub name: String, pub r#type: Type, } pub trait Actorful { - fn inputs() -> Vec<Slot>; - fn outputs() -> Vec<Slot>; + fn inputs(&self) -> Vec<Slot>; + fn outputs(&self) -> Vec<Slot>; + fn launch(&self, input_channels: HashMap<String, Receiver<Value>>, output_channels: HashMap<String, Sender<Value>>, world: &mut World); + fn boxed_clone(&self) -> Box<dyn Actorful + Send>; +} + +#[derive(Clone)] +pub enum ProducerSlotID { + Input(String), + ChildOutput(ActorId, String), +} + +#[derive(Clone)] +pub enum ConsumerSlotID { + Output(String), + ChildInput(ActorId, String), +} + +#[derive(Clone, Default)] +pub struct ProgrammableActor { + pub inputs: Vec<Slot>, + pub outputs: Vec<Slot>, + pub children: HashMap<ActorId, String>, + pub cables: Vec<(ProducerSlotID, ConsumerSlotID)>, +} + +impl ProgrammableActor { + pub fn add_child(&mut self, actor_type: String) -> ActorId { + let id = ActorId(Uuid::new_v4()); + self.children.insert(id, actor_type); + id + } + + pub fn add_cable(&mut self, in_slot: ProducerSlotID, out_slot: ConsumerSlotID) { + self.cables.push((in_slot, out_slot)); + } +} + +impl Actorful for ProgrammableActor { + fn inputs(&self) -> Vec<Slot> { + self.inputs.clone() + } + + fn outputs(&self) -> Vec<Slot> { + self.outputs.clone() + } + + fn launch(&self, mut input_channels: HashMap<String, Receiver<Value>>, mut output_channels: HashMap<String, Sender<Value>>, world: &mut World) { + let mut child_channels = HashMap::new(); + for (&child_id, child_type) in &self.children { + let (_, child_inputs, child_outputs) = world.spawn_actor(child_type); + child_channels.insert(child_id, (child_inputs, child_outputs)); + } + for (source, dest) in &self.cables { + let source = match source { + ProducerSlotID::Input(name) => input_channels.remove(name).unwrap(), + ProducerSlotID::ChildOutput(id, name) => child_channels[id].1.remove(name).unwrap() + }; + let dest = match dest { + ConsumerSlotID::Output(name) => output_channels.remove(name).unwrap(), + ConsumerSlotID::ChildInput(id, name) => child_channels[id].0.remove(name).unwrap() + }; + thread::spawn(move || { + for val in source.iter() { + dest.send(val).unwrap() + } + }); + } + } + + fn boxed_clone(&self) -> Box<dyn Actorful + Send> { + Box::new(self.clone()) + } } |