TableSelect

One field out of a table, on the output that matches what the field holds.

TableSelect rs
input
array
string
table
Type name
signal:TableSelect
Plane
signal
Tags
transform
Language
rust
Tier
native
Bundle
signal
Source
node-bundles/signal/TableSelect.rs
Availability
available

Slots

SlotDirectionType
inputinputTABLE
arrayoutputARRAY
stringoutputSTRING
tableoutputTABLE

Parameters

table

NameTypeDefaultRangeDoc
keystring""Which field to take. `a.b.c` reaches through a table inside a table.

common

NameTypeDefaultRangeDoc
autotriggerboolfalseRun on the node's own schedule, instead of waiting for an input frame. Turn this on for sources; leave it off for transforms driven by their input.
max_frequencyfloat00 … 100Rate cap for this node, read through `frequency_mode`. 0 means uncapped — the node runs as often as the scheduler and its inputs allow.
frequency_modestringupdates_per_secondupdates_per_second | seconds_per_updateHow to read `max_frequency`: as a rate in Hz (updates per second), or as a period in seconds between updates — convenient for very slow nodes.

Source

The current source of this node, as it stands in the goofi repository at node-bundles/signal/TableSelect.rs.

node-bundles/signal/TableSelect.rs
//! TableSelect — one field out of a table, on the output that matches what the field holds.
//! `a.b.c` reaches through a table inside a table.

use goofi_core::{Data, SlotType, Value};
use goofi_signal_sdk::{Inputs, Manifest, Node, NodeCtx, NodeResult, OutputDecl, Outputs, ParamDecl, Params, ParamSpec, SlotDecl, Tag};

#[derive(Default)]
struct TableSelect;

impl Node for TableSelect {
    fn process(
        &mut self,
        inp: &Inputs<'_>,
        out: &mut Outputs<'_>,
        _c: &mut NodeCtx,
        p: &Params<'_>,
    ) -> NodeResult {
        let d = inp.get("input").ok_or("`input` is required")?;
        let key = p.str("table", "key").unwrap_or("").trim();
        if key.is_empty() {
            return Err("`key` names the field to take".to_string().into());
        }
        let mut here: &Data = d;
        for step in key.split('.') {
            let table = here.as_table()?;
            here = table.get(step).ok_or_else(|| {
                format!("no `{step}` here; this table holds {:?}", table.keys().collect::<Vec<_>>())
            })?;
        }
        let slot = match here.value() {
            Value::Array(_) => "array",
            Value::Str(_) => "string",
            Value::Table(_) => "table",
        };
        out.set(slot, here.clone());
        Ok(())
    }
}

static PARAMS: &[ParamDecl] = &[ParamDecl {
    group: "table",
    name: "key",
    spec: ParamSpec::Str { default: "", options: &[], refresh: false },
    expression: None,
    doc: Some("Which field to take. `a.b.c` reaches through a table inside a table."),
}];
static INPUTS: &[SlotDecl] = &[SlotDecl {
    name: "input",
    kind: SlotType::Table,
    trigger_process: true,
    multi: false,
    required: true,
}];
static OUTPUTS: &[OutputDecl] = &[
    OutputDecl { name: "array", kind: SlotType::Array },
    OutputDecl { name: "string", kind: SlotType::String },
    OutputDecl { name: "table", kind: SlotType::Table },
];

static MANIFEST: Manifest = Manifest {
    tags: &[Tag::Transform],
    doc: "One field out of a table, on the output that matches what the field holds.",
    inputs: INPUTS,
    outputs: OUTPUTS,
    params: PARAMS,
    producer: false,
};

goofi_signal_sdk::export!(TableSelect, MANIFEST);

← All nodes

This reference describes goofi 3.1.0(537cd394), generated from a running instance on 2026-09-06.