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()) +    }  } |