diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-03-03 21:03:24 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-03-03 21:03:24 +1300 |
commit | b2374eb1746f54f58ecf1a3ac5d375b3d0f15da0 (patch) | |
tree | 9a1317044d582c94796d748ae6f517ff388137c4 | |
parent | 8a43a02b6950455aedbbdbee737bee1654aa91ef (diff) | |
download | switchboard-b2374eb1746f54f58ecf1a3ac5d375b3d0f15da0.zip |
Report malformed switches as errors
Previously, malformed arguments were silently ignored when encountered.
This could cause unexpected behaviour if the malformed argument is
safety critical, so now an error is reported.
-rw-r--r-- | src/lib.rs | 3 | ||||
-rw-r--r-- | src/query.rs | 6 | ||||
-rw-r--r-- | src/switchboard.rs | 37 |
3 files changed, 27 insertions, 19 deletions
@@ -23,7 +23,8 @@ impl std::fmt::Display for SwitchName { } } -pub enum QueryError { +pub enum SwitchboardError { + Malformed(String), MissingNamed(String), MissingPositional(String), // String is the debug name of the switch diff --git a/src/query.rs b/src/query.rs index 5a9d4ae..1cd5492 100644 --- a/src/query.rs +++ b/src/query.rs @@ -51,7 +51,7 @@ impl NamedSwitchQuery<'_> { match self.get_value() { Some(value) => self.insert(Some(value)), None => { - let error = QueryError::MissingNamed(self.debug_name()); + let error = SwitchboardError::MissingNamed(self.debug_name()); self.switchboard.errors.push(error); } } @@ -94,7 +94,7 @@ impl NamedSwitchQuery<'_> { } } _ => { - let error = QueryError::Repeated(self.debug_name()); + let error = SwitchboardError::Repeated(self.debug_name()); self.switchboard.errors.push(error); None } @@ -153,7 +153,7 @@ impl PositionalSwitchQuery<'_> { match self.switchboard.pop() { Some(value) => self.insert(Some(value)), None => { - let error = QueryError::MissingPositional(self.name.clone()); + let error = SwitchboardError::MissingPositional(self.name.clone()); self.switchboard.errors.push(error); } } diff --git a/src/switchboard.rs b/src/switchboard.rs index f19db13..1c3ed81 100644 --- a/src/switchboard.rs +++ b/src/switchboard.rs @@ -15,7 +15,7 @@ pub struct Switchboard { // All queried values. pub values: HashMap<String, QueriedValue>, // All query errors - pub errors: Vec<QueryError>, + pub errors: Vec<SwitchboardError>, // Total number of popped positional arguments pub i: usize, } @@ -26,6 +26,7 @@ impl Switchboard { let mut switches = Vec::new(); let mut unprocessed = None; let mut args = VecDeque::from(args); + let mut errors = Vec::new(); while let Some(arg) = args.pop_front() { if arg.is_empty() { @@ -33,23 +34,27 @@ impl Switchboard { } else if arg == "--" { unprocessed = Some(Vec::from(args)); break; - } else if let Some(arg) = arg.strip_prefix("--") { - let (name, value) = match arg.split_once("=") { + } else if let Some(stripped) = arg.strip_prefix("--") { + let (name, value) = match stripped.split_once("=") { Some((name, "")) => (name, None), Some((name, value)) => (name, Some(value.to_string())), - None => (arg, None), + None => (stripped, None), }; - if name.is_empty() { continue } - switches.push((SwitchName::Long(name.to_string()), value)); - } else if let Some(arg) = arg.strip_prefix("-") { - let (name, value) = match arg.split_once("=") { + match !name.is_empty() { + true => switches.push((SwitchName::Long(name.to_string()), value)), + false => errors.push(SwitchboardError::Malformed(arg.to_string())), + } + } else if let Some(stripped) = arg.strip_prefix("-") { + let (name, value) = match stripped.split_once("=") { Some((name, "")) => (name, None), Some((name, value)) => (name, Some(value.to_string())), - None => (arg, None), + None => (stripped, None), }; let chars: Vec<char> = name.chars().collect(); - if chars.len() != 1 { continue } - switches.push((SwitchName::Short(chars[0]), value)); + match chars.len() == 1 { + true => switches.push((SwitchName::Short(chars[0]), value)), + false => errors.push(SwitchboardError::Malformed(arg.to_string())), + } } else { positional.push(arg) } @@ -58,7 +63,6 @@ impl Switchboard { positional.reverse(); let program = positional.pop().unwrap(); let values = HashMap::new(); - let errors = Vec::new(); let i = 0; Self { program, positional, switches, unprocessed, values, errors, i @@ -109,15 +113,18 @@ impl Switchboard { } for error in &self.errors { match error { - QueryError::MissingNamed(name) => { + SwitchboardError::MissingNamed(name) => { error!("The {name} switch is required") } - QueryError::MissingPositional(name) => { + SwitchboardError::MissingPositional(name) => { error!("The <{name}> argument is required") } - QueryError::Repeated(name) => { + SwitchboardError::Repeated(name) => { error!("The {name} switch was passed multiple times") } + SwitchboardError::Malformed(string) => { + error!("The '{string}' argument is malformed") + } } } std::process::exit(1); |