Skip to main content

lyris/core/
builder.rs

1use super::types::*;
2use crate::{core::Clerk, Runtime, Router};
3use std::collections::HashMap;
4use std::any::{TypeId, Any};
5use std::cell::UnsafeCell;
6use std::sync::{Arc, Mutex};
7use std::fmt::Debug;
8use super::processor::{Processor, SystemInput, SystemOutput};
9
10pub struct Builder<E: Clone + Copy + Debug + 'static>{
11    components: Vec<(TypeId, &'static str, StoredComponent<E>)>,
12    next_component_id: usize,
13    buffer_size: usize,
14    states: Vec<Box<UnsafeCell<dyn Any + Send + 'static>>>,
15}
16
17impl<E: Clone + Copy + Debug> Builder<E> {
18    pub fn new() -> Self {
19        Self {
20            components: Vec::new(),
21            next_component_id: 0,
22            buffer_size: 512,
23            states: Vec::new(),
24        }
25    }
26    
27    pub fn add_processor<P: Processor>(
28        mut self,
29        processor: P,
30        instance_name: &'static str,
31    ) -> Self {
32        let component_id = ComponentId(self.next_component_id);
33        self.next_component_id += 1;
34        
35        let handle = ContextHandle {
36            component_id,
37            buffer_ids_start: BufferIdx(0), // Will be set during build
38            slot_ids_start: self.states.len()
39        };
40
41        // Create a wrapper function that calls the processor's call method
42        let component_fn = |runtime: &Runtime<E>, handle: ContextHandle| {
43            P::call(runtime, handle)
44        };
45
46        let stored = UserComponent {
47            component: component_fn,
48            context_handle: handle,
49            field_count: P::buffers_count(),
50            instance_name,
51            processor_type: TypeId::of::<P>(),
52        };
53
54        self.components.push((TypeId::of::<P>(), instance_name, StoredComponent::User(stored)));
55        self
56    }
57
58    pub fn add<P: Processor>(mut self, processor: P) -> Self {
59        let component_id = ComponentId(self.next_component_id);
60        self.next_component_id += 1;
61        
62        let handle = ContextHandle {
63            component_id,
64            buffer_ids_start: BufferIdx(0), // Set during build
65            slot_ids_start: self.states.len(),
66        };
67
68        self.states.extend(P::create_states());
69
70        // use type name for unique, hashable identifier
71        let instance_name = std::any::type_name::<P>();
72        
73        let stored = UserComponent {
74            component: P::call,
75            context_handle: handle,
76            field_count: P::buffers_count(),
77            instance_name: instance_name,
78            processor_type: TypeId::of::<P>(),
79        };
80        
81        self.components.push((TypeId::of::<P>(), instance_name, StoredComponent::User(stored)));
82        self
83    }
84
85    pub fn buffer_length(mut self, length: usize) -> Self {
86        self.buffer_size = length;
87        self
88    }
89    
90    pub fn build(self) -> (Runtime<E>, Router<E>) {
91        let (update_tx, update_rx) = lockfree::channel::spsc::create();
92        let (event_tx, event_rx) = lockfree::channel::spsc::create();
93        
94        let mut components = HashMap::new();
95
96        let input_component = StoredComponent::System(SystemComponent {
97            component_id: ComponentId(0),
98            instance_name: "__system_input__",
99            buffer_idx: BufferIdx(0), // will be configured during routing!
100        });
101        components.insert((TypeId::of::<SystemInput>(), "__system_input__"), input_component);
102
103        let output_component = StoredComponent::System(SystemComponent {
104            component_id: ComponentId(1), 
105            instance_name: "__system_output__",
106            buffer_idx: BufferIdx(0), // will be configured during routing!
107        });
108        components.insert((TypeId::of::<SystemOutput>(), "__system_output__"), output_component);
109        
110        for (type_id, name, stored) in self.components {
111            components.insert((type_id, name), stored);
112        }
113        
114        let clerk = Arc::new(Mutex::new(Clerk::new(components, self.buffer_size, update_tx, event_tx)));
115        
116        let router = Router {
117            clerk: Arc::clone(&clerk),
118        };
119        
120        let runtime = Runtime::new(update_rx, event_rx, self.states, self.buffer_size);
121        
122        (runtime, router)
123    }
124
125}