aboutsummaryrefslogtreecommitdiff
path: root/src/actor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/actor.rs')
-rw-r--r--src/actor.rs93
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())
+ }
}