use std::collections::BTreeMap;
#[derive(Clone, Debug)]
pub struct Command<'a> {
command: &'a str,
parameters: BTreeMap<&'a str, &'a str>,
options: Vec<&'a str>,
arguments: Vec<&'a str>,
}
impl<'a> Command<'a> {
pub fn get_command(&self) -> &'a str {
self.command
}
pub fn get_parameters(&self) -> &BTreeMap<&'a str, &'a str> {
&self.parameters
}
pub fn get_parameter(&self, name: &'a str) -> Option<&&'a str> {
self.parameters.get(name)
}
pub fn get_options(&self) -> &Vec<&'a str> {
&self.options
}
pub fn is_option(&self, name: &'a str) -> bool {
self.options.contains(&name)
}
pub fn get_arguments(&self) -> &Vec<&'a str> {
&self.arguments
}
pub fn get_argument(&self, index: usize) -> Option<&&'a str> {
self.arguments.get(index)
}
pub fn from_string(raw: &'a [String], filter_options: &[&str]) -> Self {
Self::from(
&raw.iter().map(|s| &**s).collect::<Vec<&'a str>>()[..],
filter_options,
)
}
pub fn without_options(raw: &[&'a str]) -> Self {
Self::from(raw, &[])
}
pub fn without_command(raw: &[&'a str], filter_options: &[&str]) -> Self {
let raw_with_command = [&[""], &raw[..]].concat();
Self::from(&raw_with_command, filter_options)
}
pub fn without_command_and_options(raw: &[&'a str]) -> Self {
let raw_with_command = [&[""][..], &raw[..]].concat();
Self::from(&raw_with_command, &[])
}
pub fn from(raw: &[&'a str], filter_options: &[&str]) -> Self {
let command = match raw.get(0) {
Some(command) => command,
None => "",
};
let mut parameters: BTreeMap<&str, &str> = BTreeMap::new();
let mut options: Vec<&str> = Vec::new();
let mut arguments: Vec<&str> = Vec::new();
let mut parameter = "";
let mut is_parameter = false;
for (index, argument) in raw.iter().enumerate() {
if index == 0 {
continue;
}
if is_parameter {
parameters.insert(parameter, argument);
parameter = "";
is_parameter = false;
} else {
let process_split = |parameters: &mut BTreeMap<&'a str, &'a str>,
parameter: &mut &'a str,
is_parameter: &mut bool,
argument: &'a str| {
let splits = argument.splitn(2, '=');
for split in splits {
if *is_parameter {
parameters.insert(parameter, split);
*is_parameter = false;
} else {
*parameter = split;
*is_parameter = true;
}
}
};
if argument.starts_with("--") {
let cut = match argument.len() {
len if len >= 3 => &argument[2..],
_ => argument,
};
if filter_options.contains(&cut) {
options.push(cut);
continue;
}
process_split(&mut parameters, &mut parameter, &mut is_parameter, cut);
} else if argument.starts_with('-') {
let cut = match argument.len() {
len if len >= 2 => &argument[1..],
_ => argument,
};
if filter_options.contains(&cut) {
options.push(cut);
continue;
}
process_split(&mut parameters, &mut parameter, &mut is_parameter, cut);
} else {
arguments.push(argument);
}
}
}
if is_parameter {
options.push(parameter);
}
Self {
command,
parameters,
options,
arguments,
}
}
}
#[cfg(test)]
mod tests {
mod mod_command {
use crate::Command;
#[test]
fn from_string() {
let options = ["option1", "option2", "option3"];
let mut arguments = Vec::new();
arguments.push("command".into());
arguments.push("--param1=value1".into());
arguments.push("--param2=value2".into());
arguments.push("-short-param1=short-value1".into());
arguments.push("--option1".into());
arguments.push("-short-param2=short-value2".into());
arguments.push("--option2".into());
arguments.push("--param3".into());
arguments.push("value3".into());
arguments.push("--param4".into());
arguments.push("value4".into());
arguments.push("some".into());
arguments.push("more".into());
arguments.push("arguments".into());
let command = Command::from_string(&arguments, &options);
assert_eq!(command.get_command(), "command");
assert_eq!(*command.get_parameter("param1").unwrap(), "value1");
assert_eq!(*command.get_parameter("param2").unwrap(), "value2");
assert_eq!(*command.get_parameter("param3").unwrap(), "value3");
assert_eq!(*command.get_parameter("param4").unwrap(), "value4");
assert_eq!(
*command.get_parameter("short-param1").unwrap(),
"short-value1"
);
assert_eq!(
*command.get_parameter("short-param2").unwrap(),
"short-value2"
);
assert_eq!(command.is_option("option1"), true);
assert_eq!(command.is_option("option2"), true);
assert_eq!(command.is_option("option3"), false);
assert_eq!(*command.get_argument(0).unwrap(), "some");
assert_eq!(*command.get_argument(1).unwrap(), "more");
assert_eq!(*command.get_argument(2).unwrap(), "arguments");
assert_eq!(command.get_parameters().len(), 6);
assert_eq!(command.get_options().len(), 2);
assert_eq!(command.get_arguments().len(), 3);
}
#[test]
fn without_options() {
let mut arguments = Vec::new();
arguments.push("command");
arguments.push("--param1=value1");
arguments.push("--param2=value2");
arguments.push("-short-param1=short-value1");
arguments.push("-short-param2=short-value2");
arguments.push("--param3");
arguments.push("value3");
arguments.push("--param4");
arguments.push("value4");
arguments.push("some");
arguments.push("more");
arguments.push("arguments");
let command = Command::without_options(&arguments);
assert_eq!(command.get_command(), "command");
assert_eq!(*command.get_parameter("param1").unwrap(), "value1");
assert_eq!(*command.get_parameter("param2").unwrap(), "value2");
assert_eq!(*command.get_parameter("param3").unwrap(), "value3");
assert_eq!(*command.get_parameter("param4").unwrap(), "value4");
assert_eq!(
*command.get_parameter("short-param1").unwrap(),
"short-value1"
);
assert_eq!(
*command.get_parameter("short-param2").unwrap(),
"short-value2"
);
assert_eq!(command.is_option("option1"), false);
assert_eq!(*command.get_argument(0).unwrap(), "some");
assert_eq!(*command.get_argument(1).unwrap(), "more");
assert_eq!(*command.get_argument(2).unwrap(), "arguments");
assert_eq!(command.get_parameters().len(), 6);
assert_eq!(command.get_options().len(), 0);
assert_eq!(command.get_arguments().len(), 3);
}
#[test]
fn without_command() {
let options = ["option1", "option2", "option3"];
let mut arguments = Vec::new();
arguments.push("--param1=value1");
arguments.push("--param2=value2");
arguments.push("-short-param1=short-value1");
arguments.push("--option1");
arguments.push("-short-param2=short-value2");
arguments.push("--option2");
arguments.push("--param3");
arguments.push("value3");
arguments.push("--param4");
arguments.push("value4");
arguments.push("some");
arguments.push("more");
arguments.push("arguments");
let command = Command::without_command(&arguments, &options);
assert_eq!(command.get_command(), "");
assert_eq!(*command.get_parameter("param1").unwrap(), "value1");
assert_eq!(*command.get_parameter("param2").unwrap(), "value2");
assert_eq!(*command.get_parameter("param3").unwrap(), "value3");
assert_eq!(*command.get_parameter("param4").unwrap(), "value4");
assert_eq!(
*command.get_parameter("short-param1").unwrap(),
"short-value1"
);
assert_eq!(
*command.get_parameter("short-param2").unwrap(),
"short-value2"
);
assert_eq!(command.is_option("option1"), true);
assert_eq!(command.is_option("option2"), true);
assert_eq!(command.is_option("option3"), false);
assert_eq!(*command.get_argument(0).unwrap(), "some");
assert_eq!(*command.get_argument(1).unwrap(), "more");
assert_eq!(*command.get_argument(2).unwrap(), "arguments");
assert_eq!(command.get_parameters().len(), 6);
assert_eq!(command.get_options().len(), 2);
assert_eq!(command.get_arguments().len(), 3);
}
#[test]
fn without_command_and_options() {
let mut arguments = Vec::new();
arguments.push("--param1=value1");
arguments.push("--param2=value2");
arguments.push("-short-param1=short-value1");
arguments.push("-short-param2=short-value2");
arguments.push("--param3");
arguments.push("value3");
arguments.push("--param4");
arguments.push("value4");
arguments.push("some");
arguments.push("more");
arguments.push("arguments");
let command = Command::without_command_and_options(&arguments);
assert_eq!(command.get_command(), "");
assert_eq!(*command.get_parameter("param1").unwrap(), "value1");
assert_eq!(*command.get_parameter("param2").unwrap(), "value2");
assert_eq!(*command.get_parameter("param3").unwrap(), "value3");
assert_eq!(*command.get_parameter("param4").unwrap(), "value4");
assert_eq!(
*command.get_parameter("short-param1").unwrap(),
"short-value1"
);
assert_eq!(
*command.get_parameter("short-param2").unwrap(),
"short-value2"
);
assert_eq!(command.is_option("option1"), false);
assert_eq!(*command.get_argument(0).unwrap(), "some");
assert_eq!(*command.get_argument(1).unwrap(), "more");
assert_eq!(*command.get_argument(2).unwrap(), "arguments");
assert_eq!(command.get_parameters().len(), 6);
assert_eq!(command.get_options().len(), 0);
assert_eq!(command.get_arguments().len(), 3);
}
#[test]
fn from() {
let options = ["option1", "option2", "option3"];
let mut arguments = Vec::new();
arguments.push("command");
arguments.push("--param1=value1");
arguments.push("--param2=value2");
arguments.push("-short-param1=short-value1");
arguments.push("--option1");
arguments.push("-short-param2=short-value2");
arguments.push("--option2");
arguments.push("--param3");
arguments.push("value3");
arguments.push("--param4");
arguments.push("value4");
arguments.push("some");
arguments.push("more");
arguments.push("arguments");
let command = Command::from(&arguments, &options);
assert_eq!(command.get_command(), "command");
assert_eq!(*command.get_parameter("param1").unwrap(), "value1");
assert_eq!(*command.get_parameter("param2").unwrap(), "value2");
assert_eq!(*command.get_parameter("param3").unwrap(), "value3");
assert_eq!(*command.get_parameter("param4").unwrap(), "value4");
assert_eq!(
*command.get_parameter("short-param1").unwrap(),
"short-value1"
);
assert_eq!(
*command.get_parameter("short-param2").unwrap(),
"short-value2"
);
assert_eq!(command.is_option("option1"), true);
assert_eq!(command.is_option("option2"), true);
assert_eq!(command.is_option("option3"), false);
assert_eq!(*command.get_argument(0).unwrap(), "some");
assert_eq!(*command.get_argument(1).unwrap(), "more");
assert_eq!(*command.get_argument(2).unwrap(), "arguments");
assert_eq!(command.get_parameters().len(), 6);
assert_eq!(command.get_options().len(), 2);
assert_eq!(command.get_arguments().len(), 3);
}
}
}