summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2025-03-03 21:03:24 +1300
committerBen Bridle <ben@derelict.engineering>2025-03-03 21:03:24 +1300
commitb2374eb1746f54f58ecf1a3ac5d375b3d0f15da0 (patch)
tree9a1317044d582c94796d748ae6f517ff388137c4
parent8a43a02b6950455aedbbdbee737bee1654aa91ef (diff)
downloadswitchboard-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.rs3
-rw-r--r--src/query.rs6
-rw-r--r--src/switchboard.rs37
3 files changed, 27 insertions, 19 deletions
diff --git a/src/lib.rs b/src/lib.rs
index d968cf2..0a2954d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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);