Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

App & Debugging in no_std

Compiling a no_std pipeline with std

One of the strengths of pondrs is that a pipeline written for no_std can also be compiled with std enabled. This lets you use the full App interface β€” including YAML configuration, CLI argument parsing, parameter overrides, check, and viz β€” for development and debugging, while deploying the same pipeline code to a no_std target.

Simply add pondrs as a dev-dependency with the all feature, and use App::from_args or App::from_yaml in a host-side binary or test:

// tests/run_on_host.rs β€” compiles with std
fn main() -> Result<(), PondError> {
    App::from_args(std::env::args_os())?
        .dispatch(my_no_std_pipeline)
}

This gives you visualization, validation, logging hooks, and parallel execution for free during development, without changing the pipeline itself.

App::new

In no_std environments, App::new is the only available constructor:

let app = App::new(catalog, params);
app.execute(pipeline)?;

There is no YAML loading, no CLI parsing, and no dispatch β€” you construct the catalog and params directly and call execute.

Default runner

The default runner tuple in no_std is (SequentialRunner,). The ParallelRunner requires std (threads).

Hooks in no_std

The Hook and Hooks traits work in no_std, but there are no built-in hook implementations (LoggingHook requires std). You can implement your own:

struct UartLogger;

impl Hook for UartLogger {
    fn before_node_run(&self, n: &dyn PipelineInfo) {
        // write to UART, toggle debug pin, etc.
        uart_print(n.name());
    }

    fn on_node_error(&self, n: &dyn PipelineInfo, _error: &str) {
        uart_print("ERROR: ");
        uart_print(n.name());
    }
}

App::new(catalog, params)
    .with_hooks((UartLogger,))
    .execute(pipeline)?;

Note that in no_std, the error string in on_node_error is always "node error" (not the full error message), since Display formatting requires allocation.

Dataset names

In no_std, the catalog indexer is not available, so DatasetRef::name in hook callbacks is always None. Hooks can still use ds.id (pointer-based) or ds.meta.type_string() for identification.

PondError in no_std

Only three PondError variants are available without std:

  • DatasetNotLoaded β€” a dataset was read before being written
  • RunnerNotFound β€” the specified runner name doesn’t match any runner
  • CheckFailed β€” pipeline validation failed (used by dispatch with Command::Check)

All other variants (Io, Polars, SerdeYaml, etc.) are feature-gated.

Validation

check() works fully in no_std. It uses fixed-size stack arrays instead of HashMap:

let steps = pipeline(&catalog, &params);
steps.check()?;

// For pipelines with more than 20 datasets:
steps.check_with_capacity::<64>()?;