feat: Add streams module for reactive pipeline
Introduces the streams module, defining core reactive primitives like Signal, Stream, Observer, RootStream, and PipeStream. This module lays the groundwork for building reactive data processing pipelines. Includes new types for managing reactive data flow and a basic test suite to verify the functionality of RootStream and PipeStream.
This commit is contained in:
@@ -349,6 +349,87 @@ impl crate::ast::types::Series for SeriesView {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 4b. Shared Series (Read-Only Reactive Storage)
|
||||
// ============================================================================
|
||||
|
||||
/// A read-only series that shares its underlying buffer with the pipeline engine.
|
||||
/// This is the basis for the "SharedSeries" in the Dual Series Architecture.
|
||||
#[derive(Clone)]
|
||||
pub struct SharedSeries<T: ScalarValue> {
|
||||
pub buffer: Rc<std::cell::RefCell<RingBuffer<T>>>,
|
||||
pub type_name: &'static str,
|
||||
pub converter: fn(T) -> Value,
|
||||
}
|
||||
|
||||
impl<T: ScalarValue> Debug for SharedSeries<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SharedSeries<{}>[len: {}]", self.type_name, self.buffer.borrow().len())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ScalarValue> Object for SharedSeries<T> {
|
||||
fn type_name(&self) -> &'static str {
|
||||
self.type_name
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn as_series(&self) -> Option<&dyn crate::ast::types::Series> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ScalarValue> crate::ast::types::Series for SharedSeries<T> {
|
||||
fn get_item(&self, index: usize) -> Option<Value> {
|
||||
self.buffer.borrow().get(index).map(|&v| (self.converter)(v))
|
||||
}
|
||||
}
|
||||
|
||||
/// A read-only series for Records that shares its buffers with the pipeline.
|
||||
#[derive(Clone)]
|
||||
pub struct SharedRecordSeries {
|
||||
pub layout: Arc<RecordLayout>,
|
||||
/// Each field shares an Rc<RefCell<RingBuffer>> with the Pipe that produces it.
|
||||
pub field_buffers: Vec<Rc<std::cell::RefCell<dyn SeriesMember>>>,
|
||||
}
|
||||
|
||||
impl Debug for SharedRecordSeries {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "SharedRecordSeries[fields: {}]", self.field_buffers.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl Object for SharedRecordSeries {
|
||||
fn type_name(&self) -> &'static str {
|
||||
"SharedRecordSeries"
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn as_series(&self) -> Option<&dyn crate::ast::types::Series> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::ast::types::Series for SharedRecordSeries {
|
||||
fn get_item(&self, index: usize) -> Option<Value> {
|
||||
if self.field_buffers.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut vals = Vec::with_capacity(self.field_buffers.len());
|
||||
for buffer in &self.field_buffers {
|
||||
match buffer.borrow().get_value(index) {
|
||||
Some(v) => vals.push(v),
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
|
||||
Some(Value::Record(self.layout.clone(), Rc::new(vals)))
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 5. Script Integration (RTL Registration)
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user