pub trait FunctionConfig:
Sized
+ Send
+ Sync
+ 'static {
const TEMPLATED: bool = false;
// Required methods
fn compile(input: &Value, cx: &mut CompileCx<'_>) -> Option<Self>;
fn visit(&self, v: &mut dyn ExprVisitor);
fn fields() -> &'static [FieldSpec];
fn resolve(&self, r: &mut dyn Resolver) -> Result<OwnedDataValue>;
// Provided method
fn primary_output(&self) -> Option<&Output> { ... }
}Expand description
A function’s input, compiled at build so a malformed one fails before any
message runs. #[derive(FunctionConfig)] writes the implementation.
use dataflow_rs::Expr;
use dataflow_rs::expr::{CompileCx, ExprEngine, Output};
use dataflow_rs::function::FunctionConfig;
use dataflow_rs::program::IssueCode;
use serde_json::json;
#[derive(FunctionConfig)]
struct Fetch {
/// The URL to fetch.
#[config(records)]
url: Expr<String>,
#[config(default = 5000)]
timeout_ms: Expr<u64>,
#[output(default = "data.response")]
output: Output,
}
let engine = ExprEngine::default();
let mut issues = Vec::new();
let mut cx = CompileCx::new(&engine, &mut issues);
let fetch = Fetch::compile(&json!({"url": {"var": "data.url"}}), &mut cx).unwrap();
assert_eq!(fetch.timeout_ms.constant(), Some(&5000));
assert_eq!(fetch.output.constant().unwrap().to_string(), "data.response");
assert!(fetch.url.constant().is_none());
assert!(Fetch::compile(&json!({"uri": "x"}), &mut cx).is_none());
drop(cx);
let codes: Vec<IssueCode> = issues.iter().map(|i| i.code).collect();
assert_eq!(codes, [IssueCode::LikelyTypo, IssueCode::InputParse]);
assert_eq!(issues[1].path.to_string(), "url");Two outputs need one of them marked #[output(primary)]:
use dataflow_rs::expr::Output;
use dataflow_rs::function::FunctionConfig;
#[derive(FunctionConfig)]
struct Split {
ok: Output,
failed: Output,
}The primary output, marked or the only one, is an Output or an
Option<Output>, since primary_output lends it:
use dataflow_rs::expr::Output;
use dataflow_rs::function::FunctionConfig;
#[derive(FunctionConfig)]
struct Fan {
#[output(primary)]
many: Vec<Output>,
failed: Output,
}A field merely named Output is not one: the derive asserts the type’s
ConfigField::IS_OUTPUT, so an implementor that leaves it false is
refused instead of silently compiling as a destination:
use dataflow_rs::expr::{CompileCx, ConfigField, FieldKind, Resolver};
use dataflow_rs::function::FunctionConfig;
struct Output;
impl ConfigField for Output {
fn compile(_raw: &serde_json::Value, _cx: &mut CompileCx<'_>) -> Option<Self> {
Some(Self)
}
fn resolve(
&self,
_r: &mut dyn Resolver,
) -> dataflow_rs::Result<Option<dataflow_rs::datavalue::OwnedDataValue>> {
Ok(None)
}
fn kind() -> FieldKind {
FieldKind::Output
}
}
#[derive(FunctionConfig)]
struct Writes {
out: Output,
}The derive refuses what it cannot honour. An unknown config key:
#[derive(FunctionConfig)]
struct Unknown {
#[config(renamed = "k")]
a: bool,
}A generic struct, even one whose parameter is a config field:
#[derive(FunctionConfig)]
struct Generic<T: ConfigField> {
a: T,
}A tuple struct:
#[derive(FunctionConfig)]
struct Tuple(bool);records on a serde field, which holds no expression to record:
#[derive(FunctionConfig)]
struct Recorded {
#[config(serde, records)]
a: Option<bool>,
}A serde field whose type is not Serialize, which
resolve reads it through:
#[derive(serde::Deserialize)]
enum Mode {
Fast,
}
#[derive(FunctionConfig)]
struct Unserialized {
#[config(serde)]
mode: Mode,
}A key given twice on one field:
#[derive(FunctionConfig)]
struct Renamed {
#[config(rename = "a", rename = "b")]
x: bool,
}A default_json that is not JSON, refused where it is written rather than
when a definition is first compiled:
#[derive(FunctionConfig)]
struct BadDefault {
#[config(default_json = "{not json")]
extra: serde_json::Value,
}A hand-written config that does not say how it resolves:
use dataflow_rs::expr::{CompileCx, ExprVisitor, FieldSpec};
use dataflow_rs::function::FunctionConfig;
struct Bare;
impl FunctionConfig for Bare {
fn compile(_input: &serde_json::Value, _cx: &mut CompileCx<'_>) -> Option<Self> {
Some(Self)
}
fn visit(&self, _v: &mut dyn ExprVisitor) {}
fn fields() -> &'static [FieldSpec] {
&[]
}
}Provided Associated Constants§
Required Methods§
Sourcefn compile(input: &Value, cx: &mut CompileCx<'_>) -> Option<Self>
fn compile(input: &Value, cx: &mut CompileCx<'_>) -> Option<Self>
Every issue in the config, each at its exact path below the
CompileCx’s root. None when any is Rejected.
Sourcefn visit(&self, v: &mut dyn ExprVisitor)
fn visit(&self, v: &mut dyn ExprVisitor)
Walks the config’s expressions; paths are relative to the config’s root.
Sourcefn resolve(&self, r: &mut dyn Resolver) -> Result<OwnedDataValue>
fn resolve(&self, r: &mut dyn Resolver) -> Result<OwnedDataValue>
The config resolved for one call, through r: every field with a
value, set by the input or by its default, keyed by its authored key,
in declaration order; an Option left unset is absent. An expression
is evaluated, a document rendered, an output’s path given as its
dotted text, a nested config resolved as an object, and a
#[config(serde)] field written as it serializes (unset when that is
null, as an Option left None is). The derive generates it; a
hand-written config writes its own, as it writes
compile and visit, so one that
forgets it fails to compile rather than resolving to nothing.
Ctx::input is this over the call’s context,
with every field that reads a secret null.
§Errors
The first field’s that fails: an evaluation’s, or a serde field that does not serialize.
Provided Methods§
Sourcefn primary_output(&self) -> Option<&Output>
fn primary_output(&self) -> Option<&Output>
The output Ctx::emit_default writes
through, and an answering layer answers with: the derive returns the
field marked #[output(primary)], or the only output when there is
one (None for an Option<Output> the input did not set). A
hand-written config has none unless it says so.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl FunctionConfig for ()
The config of a function that takes no input: {} or null.
impl FunctionConfig for ()
The config of a function that takes no input: {} or null.