Skip to content

Cargo features and dependencies

rtb-config has two Cargo features and both are off by default. Everything on the API reference that is not marked with a feature works with a plain dependency line.

[dependencies]
rtb-config = "0.6"

Which feature do I need?

Feature Turns on Pulls in Default
hot-reload Config::watch_files, the WatchHandle type, the rtb_config::watch module notify, notify-debouncer-full off
mutable Config::schema, Config::write schemars, serde_json, serde_yaml, toml off
# a long-running service that reloads on file change
rtb-config = { version = "0.6", features = ["hot-reload"] }

# a CLI with `config set` / `config schema` subcommands
rtb-config = { version = "0.6", features = ["mutable"] }

# both
rtb-config = { version = "0.6", features = ["hot-reload", "mutable"] }

The features are independent — neither implies the other, and there is no combination of the two that is unsupported.

What if I call a feature-gated method without the feature?

It does not exist, so the build fails at compile time with no method named watch_files found or no function or associated item named schema found. There is no runtime fallback and nothing silently degrades.

If a method you expected is missing and the feature is enabled, check the trait bounds — write and schema also need C: Serialize + JsonSchema. See which trait bounds does my config struct need.

Why is hot-reload not on by default?

A file watcher costs an OS watch handle, a background thread and two more crates, and most consumers of a config crate are short-lived CLI invocations that read config once and exit. Making the watcher opt-in keeps that common case cheap. The same reasoning applies to mutable: a tool that never writes config back should not carry a YAML and a TOML serialiser to do it.

What does rtb-config depend on unconditionally?

Crate Why
figment The layering and merge engine, with its toml, yaml, json and env features
serde The Deserialize derive your config struct uses
arc-swap The atomic pointer swap behind get and reload
tokio tokio::sync::watch powers Config::subscribe
thiserror The ConfigError derive
miette Diagnostic codes and help text on every error variant

Two of those are worth calling out because they are larger than they need to be for what the crate uses:

  • tokio is not optional and is declared with features = ["full"], even though only tokio::sync::watch is used. If you are counting build time or binary size, that is where it goes.
  • figment is built with the toml and json features, but only its YAML and environment providers are wired up. ConfigBuilder::user_file always parses YAML — see can I use a TOML or JSON config file.

Do I need a tokio runtime?

Only to await changes. build, get, reload and write are ordinary synchronous calls and work in a program with no async runtime at all. Config::subscribe returns a tokio::sync::watch::Receiver, and rx.borrow() is synchronous too — it is rx.changed().await that needs an async context.

watch_files runs on a plain OS thread, not a tokio task, so the watcher itself does not need a runtime either.

What Rust version does this need?

Field Value
Edition 2021
MSRV (rust-version) 1.82
Toolchain used in CI pinned exactly in rust-toolchain.toml

CI pins one exact stable rather than tracking the floating stable channel, so a new rustc release cannot change the build without a reviewed toolchain bump.

The crate is #![forbid(unsafe_code)] — not deny, which a module can locally override. There is no unsafe block anywhere in the shipped code.

Next