Skip to main content

tree_api/
tree_api.rs

1//! Uses the lower-level tree API with a custom line-based config format.
2
3use std::{
4    fs, io,
5    path::{Path, PathBuf},
6    time::{SystemTime, UNIX_EPOCH},
7};
8
9use rust_config_tree::tree::{ConfigSource, ConfigTreeOptions, IncludeOrder, load_config_tree};
10
11/// Builds a demo include tree and prints traversal results.
12fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
13    let root_config = write_demo_tree()?;
14    let tree = load_config_tree(&root_config, load_source)?;
15
16    println!("declared order:");
17    for node in tree.nodes() {
18        println!("{} -> {:?}", node.path().display(), node.includes());
19    }
20
21    let reverse_tree = ConfigTreeOptions::default()
22        .include_order(IncludeOrder::Reverse)
23        .load(&root_config, load_source)?;
24
25    println!("reverse sibling order:");
26    for value in reverse_tree.into_values() {
27        println!("{}", value.lines().next().unwrap_or_default());
28    }
29
30    Ok(())
31}
32
33/// Loads the custom line-based example format from one file.
34fn load_source(path: &Path) -> io::Result<ConfigSource<String>> {
35    let content = fs::read_to_string(path)?;
36    let includes = content
37        .lines()
38        .filter_map(|line| line.strip_prefix("include="))
39        .map(PathBuf::from)
40        .collect();
41
42    Ok(ConfigSource::new(content, includes))
43}
44
45/// Creates a root file and two included files for the tree API example.
46fn write_demo_tree() -> io::Result<PathBuf> {
47    let dir = temp_example_dir("tree-api")?;
48    let config_dir = dir.join("config");
49    fs::create_dir_all(&config_dir)?;
50
51    let root_config = dir.join("root.conf");
52    fs::write(
53        &root_config,
54        "root\ninclude=config/database.conf\ninclude=config/server.conf\n",
55    )?;
56    fs::write(config_dir.join("database.conf"), "database\npool_size=16\n")?;
57    fs::write(config_dir.join("server.conf"), "server\nport=3000\n")?;
58
59    Ok(root_config)
60}
61
62/// Creates a unique temporary directory for one example run.
63fn temp_example_dir(name: &str) -> io::Result<PathBuf> {
64    let nanos = SystemTime::now()
65        .duration_since(UNIX_EPOCH)
66        .unwrap_or_default()
67        .as_nanos();
68    let dir = std::env::temp_dir().join(format!("rust-config-tree-{name}-{nanos}"));
69    fs::create_dir_all(&dir)?;
70    Ok(dir)
71}