Skip to main content

polydat_nodes/
streamer.rs

1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! The producer node (SRD 113 ยง3.1). `name := for ...` lowers to
5//! `const name := streamer("<json>")`, where the payload is the
6//! resolved comprehension serialized by [`StreamerValue::to_json`].
7//! The node parses once at setup and emits the same reflected value on
8//! every pull, so the wire is an init-time constant.
9
10use polydat::derive_support::Ext;
11use polydat::iteration::comprehension::streamer_value::StreamerValue;
12
13/// Materialize a comprehension as a `Streamer` value. Authors do not
14/// call this directly; the compiler emits it for `for` expressions.
15#[polydat::polydat_node(category = Variadic)]
16fn streamer(
17    spec: Const<&str>,
18    #[poly_const(StreamerValue::from_json, from = spec)] parsed: &StreamerValue,
19) -> Ext<StreamerValue> {
20    Ext(parsed.clone())
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use polydat::ast::{PolydatNode, Value};
27    use polydat::iteration::comprehension::ast::Comprehension;
28    use polydat::iteration::comprehension::source::Source;
29
30    #[test]
31    fn node_round_trips_the_payload() {
32        let ast = Comprehension::clause(
33            "k",
34            Source::IntRange {
35                lo: 1,
36                hi: 4,
37                step: 1,
38            },
39        );
40        let payload = StreamerValue::new("k in 1..4", ast).to_json();
41        let node = Streamer::new(payload);
42        let mut out = [Value::None];
43        node.eval(&[], &mut out);
44        let s = out[0].as_streamer().expect("streamer value");
45        assert_eq!(s.text, "k in 1..4");
46        assert_eq!(s.element_names(), vec!["k"]);
47    }
48}