miniconf 0.21.0

Serialize/deserialize/access reflection for trees
Documentation
use anyhow::Context;
use miniconf::{ConstPath, ConstPathIter, SerdeError, TreeSchema, ValueError, json_core};

mod common;
use common::Settings;

/// Simple command line interface example for miniconf
///
/// This exposes `Settings` leaves as long options such as
/// `--control-enabled false` or `--output-dac-1 2048`, then prints the tree
/// as option key-value pairs.
fn main() -> anyhow::Result<()> {
    let mut settings = Settings::new();

    let mut args = std::env::args().skip(1);
    while let Some(key) = args.next() {
        let key = key.strip_prefix('-').context("stripping option prefix")?;
        let value = args.next().context("looking for value")?;
        json_core::set_by_key(
            &mut settings,
            ConstPathIter::<'_, '-'>::root(key),
            value.as_bytes(),
        )
        .context("lookup/deserialize")?;
    }

    let mut buf = vec![0; 1024];
    const MAX_DEPTH: usize = Settings::SCHEMA.max_depth();
    for item in Settings::SCHEMA.nodes::<ConstPath<String, '-'>, MAX_DEPTH>() {
        let key = item.unwrap();
        match json_core::get_by_key(
            &settings,
            ConstPathIter::<'_, '-'>::root(key.as_ref()),
            &mut buf[..],
        ) {
            Ok(len) => {
                println!("-{} {}", key, core::str::from_utf8(&buf[..len]).unwrap());
            }
            Err(SerdeError::Value(ValueError::Absent)) => {
                let info = Settings::SCHEMA
                    .get(ConstPathIter::<'_, '-'>::root(key.as_ref()))
                    .unwrap();
                println!("-{} absent (depth: {})", key, info.depth);
            }
            err => {
                err.unwrap();
            }
        }
    }

    Ok(())
}