Skip to main content

dataflow_rs/def/
mod.rs

1//! Definitions: the authored form of workflows and tasks.
2//!
3//! A definition is plain data with raw expressions. It enters only through
4//! [`parse`] or [`parse_owned`], which also lint: one walk over the authored JSON builds
5//! a [`WorkflowDef`] and reports every issue at the path the author typed, at
6//! v3's codes for v3's rules. With [`ParseOptions::compat`] on, the compat
7//! reader rewrites v3's spellings first (see [`compat`](crate::compat)). A
8//! definition serializes in the v4 spelling, which `parse` reads back with the
9//! reader off.
10//!
11//! ```
12//! use dataflow_rs::def::{ParseOptions, parse};
13//! use dataflow_rs::program::IssueCode;
14//! use serde_json::json;
15//!
16//! let parsed = parse(
17//!     &json!({"id": "w", "tasks": [
18//!         {"id": "t", "conditon": true, "function": {"name": "f"}}
19//!     ]}),
20//!     ParseOptions::default(),
21//! );
22//! // A near miss of a known key loads, kept in the task's `ext`, and is reported.
23//! assert_eq!(parsed.issues[0].code, IssueCode::LikelyTypo);
24//! assert_eq!(parsed.issues[0].path.to_string(), "tasks[0].conditon");
25//! assert!(parsed.def.is_some());
26//! ```
27
28mod for_each;
29pub(crate) mod keys;
30mod loops;
31mod parse;
32pub(crate) mod reader;
33mod rollout;
34mod ser;
35#[cfg(test)]
36mod tests;
37mod types;
38
39pub use keys::{DefinitionKeys, definition_keys};
40pub use parse::{ParseOptions, Parsed, parse, parse_owned};
41pub(crate) use parse::{fragment_place, parse_steps, parse_with_rewrites};
42pub use rollout::{Rollout, RolloutError};
43pub use types::defaults;
44pub use types::{
45    FailurePolicy, ForEachDef, FunctionRef, GroupDef, Logic, LoopDef, NodeHeader, RejectionPolicy,
46    Status, StepDef, TaskDef, WorkflowDef, WorkflowFailurePolicy,
47};
48
49/// The deepest group nesting a definition may use.
50///
51/// Depth counts enclosing groups: a top-level group is at depth 0, so groups
52/// are accepted at depths `0..MAX_GROUP_DEPTH`, and a group at
53/// `MAX_GROUP_DEPTH` is `GROUP_TOO_DEEP`.
54pub const MAX_GROUP_DEPTH: usize = 8;
55
56/// v3's alias for `validation`, which the compat reader rewrites and no
57/// host function may take.
58const V3_VALIDATE: &str = "validate";
59
60/// The `validation` built-in's name, which the compat reader writes for
61/// [`V3_VALIDATE`].
62const VALIDATION: &str = "validation";
63
64/// Whether no host function may be registered as `name`: a name in
65/// [`BUILTIN_FUNCTIONS`], since a built-in cannot be shadowed, or `validate`,
66/// 3.x's alias for `validation`, which the compat reader rewrites before any
67/// name is looked up. [`Registry::register`](crate::Registry::register)
68/// panics on one; a host that registers names from data checks them here
69/// first.
70///
71/// ```
72/// use dataflow_rs::def::is_reserved_function;
73///
74/// assert!(is_reserved_function("map") && is_reserved_function("validate"));
75/// assert!(!is_reserved_function("http_call"));
76/// ```
77#[must_use]
78pub fn is_reserved_function(name: &str) -> bool {
79    BUILTIN_FUNCTIONS.contains(&name) || name == V3_VALIDATE
80}
81
82/// The built-in function names. They are reserved: no registration shadows
83/// one, and a task running one cannot carry `for_each`, since a built-in runs
84/// inline.
85pub const BUILTIN_FUNCTIONS: [&str; 8] = [
86    "map",
87    "validation",
88    "filter",
89    "log",
90    "parse_json",
91    "parse_xml",
92    "publish_json",
93    "publish_xml",
94];