spatialrust_runtime/
pipeline.rs1use crate::{RuntimeError, RuntimeResult, TraceEvent, TraceLevel, TraceLog};
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash)]
7pub struct PipelineStage(pub String);
8
9impl PipelineStage {
10 #[must_use]
12 pub fn new(value: impl Into<String>) -> Self {
13 Self(value.into())
14 }
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19pub struct PipelineConfig {
20 pub max_inflight: usize,
22}
23
24impl Default for PipelineConfig {
25 fn default() -> Self {
26 Self { max_inflight: 8 }
27 }
28}
29
30#[derive(Clone, Debug)]
32pub struct BoundedPipeline<T> {
33 config: PipelineConfig,
34 queue: Vec<(PipelineStage, T)>,
35 trace: TraceLog,
36}
37
38impl<T> BoundedPipeline<T> {
39 #[must_use]
41 pub fn new(config: PipelineConfig) -> Self {
42 Self { config, queue: Vec::new(), trace: TraceLog::new() }
43 }
44
45 pub fn push(&mut self, stage: PipelineStage, value: T) -> RuntimeResult<()> {
47 if self.queue.len() >= self.config.max_inflight {
48 self.trace.push(TraceEvent {
49 level: TraceLevel::Error,
50 stage: stage.0.clone(),
51 message: "capacity exceeded".into(),
52 });
53 return Err(RuntimeError::CapacityExceeded(stage.0));
54 }
55 self.trace.push(TraceEvent {
56 level: TraceLevel::Info,
57 stage: stage.0.clone(),
58 message: "enqueued".into(),
59 });
60 self.queue.push((stage, value));
61 Ok(())
62 }
63
64 pub fn pop(&mut self) -> Option<(PipelineStage, T)> {
66 if self.queue.is_empty() {
67 None
68 } else {
69 Some(self.queue.remove(0))
70 }
71 }
72
73 #[must_use]
75 pub fn trace(&self) -> &TraceLog {
76 &self.trace
77 }
78
79 #[must_use]
81 pub fn len(&self) -> usize {
82 self.queue.len()
83 }
84
85 #[must_use]
87 pub fn is_empty(&self) -> bool {
88 self.queue.is_empty()
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::{BoundedPipeline, PipelineConfig, PipelineStage};
95
96 #[test]
97 fn rejects_when_full() {
98 let mut pipe = BoundedPipeline::new(PipelineConfig { max_inflight: 1 });
99 pipe.push(PipelineStage::new("a"), 1).unwrap();
100 assert!(pipe.push(PipelineStage::new("b"), 2).is_err());
101 }
102}