use bevy::prelude::Color; use serde::Deserialize; use toml::Table; #[derive(Deserialize, Debug)] enum Val { A(String), B(usize), C(bool), } fn main() { let s = r#" [color] asdf = true [color.foo] qwert = false [color.foo.bar] hjkl = [1,2,3] [color.foo.bar.baz] Rgba = { red = 1.0, blue = 1.0, green = 1.0, alpha = 1.0 } "#; let vt = toml::from_str::(s).unwrap(); iter_all(&vt, "") .iter() .for_each(|(k, v)| println!("k {:?} :: v {:?}", k, v)); let x = get::(&vt, "color_foo_bar_baz").unwrap(); println!("{:?}", x); let y = get::>(&vt, "color_foo_bar_hjkl").unwrap(); println!("{:?}", y); let z = get::(&vt, "color_foo_qwert").unwrap(); println!("{:?}", z); } fn iter_all(t: &toml::Table, key: &str) -> Vec<(String, toml::Value)> { t.iter() .flat_map(|(k, v)| { let nk = if key == "" { k.to_string() } else { format!("{}_{}", key, k) }; match v { toml::Value::Table(nt) => iter_all(nt, nk.as_str()), _ => vec![(nk, v.clone())], } }) .collect() } fn locate(t: &toml::Table, key: &str) -> Option { t.iter().find_map(|(k, v)| { if key == k { Some(v.clone()) } else if key.starts_with(k) { let prefix = format!("{}_", k); match v { toml::Value::Table(nt) => locate(nt, key.strip_prefix(prefix.as_str()).unwrap()), _ => Some(v.clone()), } } else { None } }) } fn get<'de, T: Deserialize<'de>>(t: &toml::Table, key: &str) -> Option { locate(t, key).map(|val| val.try_into().ok()).flatten() }