Expand description
§miniconf
miniconf makes typed Rust data addressable: read a value, change it, discover
what else is there. Derive one tree and reuse it in a shell, a snapshot, an
inspector, or a protocol.
The core is no_std and needs no allocator. Serde encodes the values;
Miniconf selects them by path.
§Quick Start
Create a host executable (no hardware or network required):
cargo new miniconf-demo
cd miniconf-demo
cargo add miniconf@0.21.1Replace src/main.rs with the following and run cargo run.
Derive Tree to expose the fields of each settings struct.
use miniconf::{json_core, ConstPath, Tree, TreeSchema};
#[derive(Default, Tree)]
struct Settings {
enabled: bool,
output: Output,
}
#[derive(Default, Tree)]
struct Output {
gain: [u16; 2],
}
fn main() {
let mut settings = Settings::default();
json_core::set(&mut settings, "/enabled", b"true").unwrap();
json_core::set(&mut settings, "/output/gain/1", b"42").unwrap();
let mut buf = [0; 8];
let len = json_core::get(&settings, "/output/gain/1", &mut buf).unwrap();
assert!(settings.enabled);
assert_eq!(&buf[..len], b"42");
const DEPTH: usize = Settings::SCHEMA.max_depth();
for path in Settings::SCHEMA.nodes::<ConstPath<String, '/'>, DEPTH>() {
println!("{}", path.unwrap());
}
}This prints /enabled, /output/gain/0, and /output/gain/1.
Try adding a field: it gets a path without another dispatch table. The final
loop discovers those paths from the type’s schema. Here it uses the host’s
String; a fixed-capacity string also works when no allocator is available.
§Tree Shape
Nested trees expose their fields separately, as Output does above. A leaf is
read or written as one Serde value. On the gain field,
#[tree(with = miniconf::leaf)] would make the array one leaf:
/output/gain would read or write [0, 42] as a whole instead of exposing each
element. #[tree(rename = "level")] would change its path segment to level.
Structs, enums, arrays, tuples, Option<T>, and standard container types can be
combined into larger trees. Option branches and inactive enum variants remain
in the static schema but may return ValueError::Absent at runtime.
§Control Changes
Standard leaf updates through JSON-core and Postcard decode and finalize before assignment. Raw Serde sources deserialize in place and can leave partial changes on failure. Custom setters control their own side effects. Stage multi-leaf updates and commit after all calls succeed. Hardware updates and persistence remain application decisions.
Use #[tree(with = module)] to enforce rules for a field. The
integration fixture (examples/common.rs)
shows read-only fields and DAC range checking with a scratch copy. Metadata such
as max = "4095" describes the range; the custom deserializer enforces it.
§Reuse The Tree
Stabilizer’s miniconf-settings
uses one tree for a shell and snapshots: get and set address live values,
while snapshots walk the leaves to save and restore them. Add a field and both
consumers can reach it. The application handles USB framing, hardware updates,
and flash storage. This upper-layer crate is currently unpublished.
The checkout examples explore other consumers using the same integration fixture. Its paths and values are also used by tests and the embedded benchmark; use the small quickstart tree above for experiments.
| Example | Run | What it adds |
|---|---|---|
examples/cli.rs | cargo run --example cli -- --output-dac-1 2048 | Command-line options |
examples/packed.rs | cargo run --example packed --features postcard | A binary leaf round trip in fixed buffers |
examples/trace.rs | cargo run --example trace --features schema | Host-side JSON and JSON Schema |
examples/scpi.rs | cargo run --example scpi | Custom command syntax, not a complete SCPI implementation |
§Build A Consumer
Tree derives four independent capabilities: TreeSchema describes the
leaves, TreeSerialize reads them, TreeDeserialize writes them, and
TreeAny borrows their values through core::any::Any. An inspector can
require only the first two. The caller supplies framing, buffers, and scheduling.
Paths are one way to select a leaf. Index slices and Packed keys use the same
IntoKeys interface; Schema::transcode() converts between representations.
Compact keys belong to a particular schema, so resolve them again when the tree
changes. Schema::nodes() discovers leaves and Schema::get() looks up one
key.
Choose the leaf codec independently: json_core uses JSON byte slices,
postcard uses compact
binary payloads. miniconf_mqtt and
miniconf_coap are ready-made protocol consumers.
§Code Size
The embedded benchmark in tests/benchmark
compares the same get/set workload and codec against handwritten dispatch.
It reports program size, schema bytes, and observed stack use. The manual
handler omits discovery and reflection; the results are workload-specific,
not a worst-case stack bound. Run it with your tree when size matters.
§Limits
- Internal tree enums support unit, newtype, and skipped variants only. Enums with named fields or multi-field tuple variants should stay leaves or use a manual/custom implementation.
- Flattening is accepted only when generated lookup stays structurally unambiguous.
&strkey input is always slash-separated. Use explicit iterator types for other syntaxes or separators.- Schema semantics and metadata are feature-gated reflection data. Do not depend
on them unless
sem,meta-node, ormeta-edgeis enabled as needed.
§Features
derive: re-export derive macros fromminiconf_derive; enabled by default.json-core:serde_json_corehelpers for JSON byte slices.json:serde_jsonhelpers.postcard: compact binary helpers usingpostcard.sem,meta-node,meta-edge: retain structured schema semantics, node metadata, and parent-child edge metadata. Constructors and derive output accept these payloads in all builds; without the matching feature, they are discarded and schema accessors returnNoneor empty metadata.trace,schema: serde-reflection tracing and JSON Schema generation.heapless,heapless-09,alloc,std: support for the corresponding storage and platform layers.
§Stability
miniconf follows Cargo’s SemVer compatibility guidelines,
including Rust’s policy for trait implementations. For 0.y.z
releases, breaking changes bump y; compatible changes bump z.
Modules§
- compact_
schema - Compact paged schema serialization.
- deny
- Deny access tools.
- json
- Utilities using
serde_json - json_
core TreeSerialize/TreeDeserializewith “JSON and/”.- json_
schema - JSON Schema tools.
- leaf
- Leaf implementation using serde::{Serialize, Deserialize}
- passthrough
- Passthrough Tree*
- postcard
- Read and write leaf values with the Postcard binary format.
- str_
leaf TryFrom<&str>/AsRef<str>leaf- trace
- Schema tracing
Structs§
- Chain
- Concatenate two normalized key cursors.
- Const
Path - Const-specialized output path with named selector segments separated by a const separator.
- Const
Path Iter - Const-specialized path iterator for boundary key input.
- Exact
Size - Counting wrapper for iterators with known exact size
- Homogeneous
- A representative schema item for a homogeneous array
- Indices
- Sequence of child indices identifying a node in a
TreeSchema. - Internal
Schema - Static schema payload for an internal node.
- Json
Path - JSON-style path notation output.
- Json
Path Iter - JSON-style path iterator for boundary key input.
- Keys
Iter - Explicit normalized wrapper for iterator-shaped key inputs.
- Leaf
Serialize/Deserialize/Anyleaf- Lookup
- Result of an exact key lookup.
- Meta
- Immutable schema metadata.
- Named
- A named schema item
- Node
Iter - Node iterator
- Node
Schema - Shared static schema payload for one tree node.
- Numbered
- A numbered schema item
- Packed
- A bit-packed normalized key cursor over multiple child indices.
- Path
- Output path with named selector segments separated by a separator char.
- Path
Iter - Runtime-separated path iterator for boundary key input.
- Resolve
Error - Error returned by
Schema::resolve_into(). - Sem
- Structured machine-readable schema semantics.
- Shape
- Metadata about a
crate::TreeSchemanamespace.
Enums§
- Descend
Error - Errors that can occur while visiting nodes with
crate::Schema::descend(). - Internal
- An internal node with children
- KeyError
- Errors that can occur when using the Tree traits.
- Schema
- Static schema for one tree node.
- Serde
Error - Compound errors
- Ty
- Compact semantic leaf type.
- Value
Error - Errors that can occur while accessing a value.
Constants§
- MAYBE_
ABSENT_ SEM - Structured semantics for a node that may be absent at runtime.
- ONEOF_
SEM - Structured semantics for a mutually exclusive named node.
Traits§
- Into
Keys - Boundary input that can be normalized into a
Keyscursor. - Key
- Convert one selector segment into a child index for an internal node schema.
- Keys
- Normalized cursor over selector segments.
- Transcode
- Look up a key path in a
Schemaand transcode it. - TreeAny
- Access any node by a normalized key cursor.
- Tree
Deserialize - Deserialize a leaf node by a normalized key cursor.
- Tree
Deserialize Owned - Shorthand for owned deserialization through
TreeDeserialize. - Tree
Deserializer - A source for deserializing tree leaves.
- Tree
Schema - Traversal and iteration of key paths in a tree.
- Tree
Serialize - Serialize a leaf node by a normalized key cursor.
Derive Macros§
- Tree
- Derive the
TreeSchema,TreeSerialize,TreeDeserialize, andTreeAnytraits for a struct or enum. - TreeAny
- Derive the
TreeAnytrait for a struct or enum. - Tree
Deserialize - Derive the
TreeDeserializetrait for a struct or enum. - Tree
Schema - Derive the
TreeSchematrait for a struct or enum. - Tree
Serialize - Derive the
TreeSerializetrait for a struct or enum.