summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-09-09 14:32:21 -0400
committerpommicket <pommicket@gmail.com>2025-09-09 14:32:21 -0400
commitb52a9d0b6a2c15b1bebbd5ffa5481fdf25148556 (patch)
tree68184649419570f4c1def1bbce80a2bcc52f7930
parent8d2b61549d4c5924345e93130b50499b35db9ccb (diff)
Add list parsing test, fix list parsing
-rw-r--r--src/lib.rs21
-rw-r--r--src/tests/interpretation.rs24
2 files changed, 39 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 3e3c8d6..ffd8235 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,6 +5,7 @@
#![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;
@@ -271,10 +272,24 @@ fn parse_bool(location: &Location, string: &str) -> Result<bool> {
fn parse_list(string: &str) -> Vec<String> {
let mut list = vec![];
let mut item = String::new();
+ let mut push = |item: &mut String, push_empty: bool| {
+ let mut item = take(item);
+ while item.ends_with([' ', '\t']) {
+ item.pop();
+ }
+ let leading_space_stripped = item.trim_start_matches([' ', '\t']);
+ if push_empty || !leading_space_stripped.is_empty() {
+ list.push(if leading_space_stripped.len() == item.len() {
+ item
+ } else {
+ leading_space_stripped.to_owned()
+ });
+ }
+ };
let mut chars = string.chars();
while let Some(c) = chars.next() {
if c == ',' {
- list.push(item);
+ push(&mut item, true);
item = String::new();
} else if c == '\\' {
if let Some(next) = chars.next() {
@@ -292,9 +307,7 @@ fn parse_list(string: &str) -> Vec<String> {
item.push(c);
}
}
- if !item.is_empty() {
- list.push(item);
- }
+ push(&mut item, false);
list
}
diff --git a/src/tests/interpretation.rs b/src/tests/interpretation.rs
index 64106af..c5ca109 100644
--- a/src/tests/interpretation.rs
+++ b/src/tests/interpretation.rs
@@ -2,8 +2,28 @@ use crate::Configuration;
use std::error::Error;
use std::fmt::Display;
-fn do_list_test(_cfg: &Configuration) -> Result<(), Box<dyn Error>> {
- todo!()
+fn do_list_test(cfg: &Configuration) -> Result<(), Box<dyn Error>> {
+ for key in cfg.keys() {
+ let list = cfg
+ .get_list(&format!("{key}.list"))
+ .ok_or_else(|| format!("expected {key}.list to exist"))?;
+ let sep = cfg
+ .get(&format!("{key}.sep"))
+ .ok_or_else(|| format!("expected {key}.sep to exist"))?;
+ let sep: Vec<&str> = if let Some(sep) = sep.strip_suffix(';') {
+ sep.split(';').collect()
+ } else if sep.is_empty() {
+ vec![]
+ } else {
+ return Err(format!("expected {key}.sep value to end in semicolon: {sep:?}").into());
+ };
+ if sep != list {
+ Err(format!(
+ "list {key}.list parsed incorrectly: got {list:?}, expected {sep:?}"
+ ))?;
+ }
+ }
+ Ok(())
}
fn do_goodbad_test<I: PartialEq + Display>(