From 323fbd1a50643e6834f66de22d7524979ee5bff7 Mon Sep 17 00:00:00 2001 From: pommicket Date: Tue, 9 Sep 2025 02:31:58 -0400 Subject: Various fixes, misc() test for stuff not in spec tests --- src/lib.rs | 24 +++++++++++++++++------- src/tests/mod.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7d90ec4..77990bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ #![warn(clippy::redundant_closure_for_method_calls)] extern crate alloc; -use alloc::borrow::ToOwned; use alloc::boxed::Box; use alloc::string::String; use alloc::sync::Arc; @@ -698,7 +697,10 @@ impl Configuration { let start_idx = self.subkey_start_idx(key); let end_idx = self.subkey_end_idx(key); Configuration { - items: self.items[start_idx..end_idx].to_owned(), + items: self.items[start_idx..end_idx] + .iter() + .map(|(k, v)| (k[key.len() + 1..].into(), v.clone())) + .collect(), } } @@ -855,17 +857,25 @@ impl Configuration { /// Get value associated with `key`, and parse it as a comma-separated list, or else use `default`. /// + /// If you want `default = []`, use [`Self::get_list_or_empty`] instead + /// (this method will be cumbersome to use since Rust can't infer the type of `[]`). + /// /// Commas in list entries can be escaped with `\,`. /// - /// `default` can be anything that can be converted into an iterator of strings, - /// e.g. `Vec<&str>`, `Vec`, `&[&str]`, etc. + /// `default` can be any iterable-of-strings + /// (e.g. `&[&str]`, `Vec`, etc.). pub fn get_list_or_default(&self, key: &str, default: L) -> Vec where L: IntoIterator, - L::Item: AsRef, + String: From, { self.get_list(key) - .unwrap_or_else(|| default.into_iter().map(|s| s.as_ref().to_owned()).collect()) + .unwrap_or_else(|| default.into_iter().map(String::from).collect()) + } + /// Get value associated with `key`, and parse it as a comma-separated list, or else use `[]`. + pub fn get_list_or_empty(&self, key: &str) -> Vec { + let empty: [&'static str; 0] = []; + self.get_list_or_default(key, empty) } /// Merge `conf` into `self`, preferring values in `conf`. @@ -894,7 +904,7 @@ impl Configuration { } } -/// Opaque type returned by [`<&Configuration>::into_iter`]. +/// Opaque type returned by [`Configuration::iter`]. #[derive(Clone, Debug)] pub struct ConfigurationIter<'a>(core::slice::Iter<'a, (Box, Value)>); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 97a3a29..644c131 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -2,6 +2,8 @@ mod errors; mod locations; mod parsing; +use crate::Configuration; + fn do_tests_in_dir( dir: &str, ext: &str, @@ -32,3 +34,39 @@ fn do_tests_in_dir( panic!("Error: {e}"); } } + +#[test] +fn misc() { + let conf = Configuration::load( + "", + " +a = yes +[foo] +x = 5 +bar.y = 6 +" + .as_bytes(), + ) + .unwrap(); + // test section + assert_eq!(conf.section("foo").get("x"), Some("5")); + assert_eq!(conf.section("foo").get("bar.y"), Some("6")); + assert_eq!(conf.section("foo.bar").get("y"), Some("6")); + assert_eq!(conf.section("fob").get("x"), None); + // test get_or_default + assert_eq!(conf.get_or_default("foo.x", ""), "5"); + assert_eq!(conf.get_or_default("foo.y", ""), ""); + assert_eq!(conf.get_int_or_default("foo.x", 0).unwrap(), 5); + assert_eq!(conf.get_int_or_default("foo.y", 0).unwrap(), 0); + assert_eq!(conf.get_float_or_default("foo.x", 0.0).unwrap(), 5.0); + assert_eq!(conf.get_float_or_default("foo.y", 0.0).unwrap(), 0.0); + assert!(conf.get_bool_or_default("a", false).unwrap()); + assert!(!conf.get_bool_or_default("aa", false).unwrap()); + assert_eq!(conf.get_list_or_default("a", ["a"]), ["yes"]); + assert_eq!(conf.get_list_or_default("aa", ["a"]), ["a"]); + assert_eq!(conf.get_list_or_empty("a"), ["yes"]); + assert!(conf.get_list_or_empty("aa").is_empty()); + let mut keys: Vec<_> = conf.keys().collect(); + keys.sort(); + assert_eq!(keys, ["a", "foo"]); +} -- cgit v1.2.3