sim_lib_stream_combinators/
cookbook.rs1use sim_kernel::{Expr, NumberLiteral, Symbol};
4
5use crate::stream_window_data_kind;
6
7pub fn pipeline_stages_demo() -> Expr {
9 Expr::Map(vec![
10 (field("kind"), sym("stream-combinators", "pipeline")),
11 (
12 field("stages"),
13 Expr::Vector(vec![
14 sym("stream/stage", "map"),
15 sym("stream/stage", "filter-data-kind"),
16 Expr::Symbol(stream_window_data_kind()),
17 sym("stream/stage", "record"),
18 sym("stream/stage", "replay"),
19 ]),
20 ),
21 (field("window-size"), number(4)),
22 (field("modeled-source"), sym("stream/source", "memory-data")),
23 ])
24}
25
26fn field(name: &str) -> Expr {
27 Expr::Symbol(Symbol::qualified("stream-combinators", name))
28}
29
30fn sym(namespace: &str, name: &str) -> Expr {
31 Expr::Symbol(Symbol::qualified(namespace, name))
32}
33
34fn number(value: impl ToString) -> Expr {
35 Expr::Number(NumberLiteral {
36 domain: Symbol::qualified("numbers", "i64"),
37 canonical: value.to_string(),
38 })
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn pipeline_demo_includes_window_data_kind() {
47 let Expr::Map(entries) = pipeline_stages_demo() else {
48 panic!("pipeline stages demo is a map")
49 };
50 assert!(entries.iter().any(|(_, value)| {
51 matches!(value, Expr::Vector(stages) if stages.iter().any(|stage| matches!(stage, Expr::Symbol(symbol) if *symbol == stream_window_data_kind())))
52 }));
53 }
54}