Skip to main content

ConfigField

Trait ConfigField 

Source
pub trait ConfigField:
    Sized
    + Send
    + Sync
    + 'static {
    const NULL_IS_VALUE: bool = false;
    const IS_OUTPUT: bool = false;

    // Required methods
    fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>;
    fn resolve(&self, r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>;
    fn kind() -> FieldKind;

    // Provided methods
    fn absent() -> Option<Self> { ... }
    fn visit(&self, _v: &mut Visit<'_>) { ... }
}
Expand description

A type a config is made of.

An Option<T> field is optional: an absent key is None, and so is an explicit null, unless T takes null as a value (NULL_IS_VALUE), as an Expr, an Interpolated document and any JSON value do. There the null is compiled as T: map’s "logic": null is a constant null expression, not a missing logic.

A host writes its own field type by implementing it: here a connector’s name, a newtype over an Expr<String>, compiled, walked and resolved as the expression is, so a derived config holding one checks its secrets and template keys, and resolves it, as it would the expression.

use dataflow_rs::datavalue::OwnedDataValue;
use dataflow_rs::expr::{CompileCx, ConfigField, FieldKind, Resolver, ValueKind, Visit};
use dataflow_rs::function::{FunctionConfig, testing};
use dataflow_rs::{Ctx, Expr, Function, Message, Outcome, Result};
use serde_json::{Value, json};

/// The connector a call reaches, by name.
struct Connector(Expr<String>);

impl ConfigField for Connector {
    fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self> {
        Expr::<String>::compile(raw, cx).map(Self)
    }
    fn visit(&self, v: &mut Visit<'_>) {
        v.expr(self.0.raw());
    }
    fn resolve(&self, r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>> {
        r.eval(&self.0).map(Some)
    }
    fn kind() -> FieldKind {
        FieldKind::Expr(ValueKind::String)
    }
}

#[derive(FunctionConfig)]
struct Query {
    connector: Connector,
    limit: Option<Expr<u64>>,
}

/// Writes its input, as a layer or a dry run reads it, at `data.input`.
struct Echo;

impl Function for Echo {
    type Config = Query;

    async fn call(&self, ctx: &mut Ctx<'_>, _cfg: &Query) -> Result<Outcome> {
        let input = ctx.input()?;
        ctx.set(&"data.input".parse()?, input)?;
        Ok(Outcome::Ok)
    }
}

let input = json!({"connector": {"cat": ["db-", {"var": "data.region"}]}});
let data = OwnedDataValue::from(&json!({"region": "eu"}));
let out = testing::call(Echo, input)
    .message(Message::from_parts(OwnedDataValue::Null, data, OwnedDataValue::Null))
    .await;
assert_eq!(out.outcome.unwrap(), Outcome::Ok);
// The field resolved at its key; the `Option` left unset is absent.
let at = "data.input".parse().unwrap();
let written = out.message.context().get(&at).unwrap();
assert_eq!(serde_json::to_string(written).unwrap(), r#"{"connector":"db-eu"}"#);

Provided Associated Constants§

Source

const NULL_IS_VALUE: bool = false

Whether null is one of the type’s values. When it is not, an explicit null in an Option<Self> field means None.

Source

const IS_OUTPUT: bool = false

Whether the field is an output: a destination its call writes to. false unless the type is Output or an Option of one. The derive reads a field typed Output or marked #[output] as an output and asserts that this is true, so a type that merely shares the name is refused at compile time.

Required Methods§

Source

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Compiles raw; None after recording at least one issue.

Source

fn resolve(&self, r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

The field’s value for this call, resolved through r, or None when it has none (an Option the input left unset, with no default). The value sits where Self::visit reports the field’s expressions: a list’s elements at their indices, a map’s values at their keys, and an element left unset is null, keeping its place.

§Errors

The resolver’s, for the first expression or document that fails.

Source

fn kind() -> FieldKind

What the field is.

Provided Methods§

Source

fn absent() -> Option<Self>

The value when the key is absent and no default is declared. None makes the field required.

Source

fn visit(&self, _v: &mut Visit<'_>)

Reports the field’s expressions.

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 ConfigField for OwnedDataValue

Source§

const NULL_IS_VALUE: bool = true

Source§

fn compile(raw: &Value, _cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for String

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for Value

Source§

const NULL_IS_VALUE: bool = true

Source§

fn compile(raw: &Value, _cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for bool

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for f64

A float, written as one: 2.0 stays 2.0, as the JSON bridge keeps a float literal, where OwnedDataValue’s From<f64> would make it the integer 2.

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for i32

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for i64

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for u8

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for u16

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for u32

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for u64

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl ConfigField for usize

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn resolve(&self, _r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl<T: ConfigField> ConfigField for BTreeMap<String, T>

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn visit(&self, v: &mut Visit<'_>)

Source§

fn resolve(&self, r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl<T: ConfigField> ConfigField for Option<T>

Source§

const NULL_IS_VALUE: bool = true

null is None, or T’s own null.

Source§

const IS_OUTPUT: bool = T::IS_OUTPUT

An Option<Output> is an output too.

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn absent() -> Option<Self>

Source§

fn visit(&self, v: &mut Visit<'_>)

Source§

fn resolve(&self, r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Source§

impl<T: ConfigField> ConfigField for Vec<T>

Source§

fn compile(raw: &Value, cx: &mut CompileCx<'_>) -> Option<Self>

Source§

fn visit(&self, v: &mut Visit<'_>)

Source§

fn resolve(&self, r: &mut dyn Resolver) -> Result<Option<OwnedDataValue>>

Source§

fn kind() -> FieldKind

Implementors§