use std::{
error::Error,
fs::read_to_string,
io::{Read, stdin},
};
pub fn unzip_key_values(keys_values: Vec<(String, String)>) -> (Vec<String>, Vec<String>) {
let (keys, values): (Vec<String>, Vec<String>) = keys_values.into_iter().unzip();
(keys, values)
}
pub fn parse_key_val<T, U>(value: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
where
T: std::str::FromStr,
T::Err: Error + Send + Sync + 'static,
U: std::str::FromStr,
U::Err: Error + Send + Sync + 'static,
{
let n = 2;
let parts: Vec<&str> = value.splitn(n, '=').collect();
if parts.len() != n {
return Err(format!("should be formatted as key=value pair: `{value}`").into());
}
let key = parts[0].parse()?;
let value = parts[1].parse()?;
Ok((key, value))
}
pub fn read_in_source(path: Option<String>) -> String {
match path {
Some(path) => {
read_to_string(path).expect("should be able to open file at path")
}
None => {
let mut source = String::new();
stdin().read_to_string(&mut source).unwrap();
source
}
}
}
#[cfg(test)]
mod cliutil_tests {
use clap::Parser;
use crate::cliutil::{parse_key_val, read_in_source};
#[test]
fn read_in_source_from_file() {
let result = read_in_source(Some("./spec/valid/call_id.expr".to_string()));
assert_eq!("(id (noop))", result);
}
#[test]
fn parse_key_val_valid_keyvalue_pair() {
#[derive(Parser, Debug, PartialEq)]
struct Args {
#[arg(long, value_delimiter = ' ', num_args = 1.., value_parser = parse_key_val::<String, String>)]
vars: Vec<(String, String)>,
}
assert_eq!(
Args {
vars: vec![(String::from("key"), String::from("value"))]
},
Args::try_parse_from(["test", "--vars", "key=value"])
.ok()
.unwrap()
);
}
#[test]
fn parse_key_val_invalid_keyvalue_pair() {
#[derive(Parser, Debug, PartialEq)]
struct Args {
#[arg(long, value_delimiter = ' ', num_args = 1.., value_parser = parse_key_val::<String, String>)]
vars: Vec<(String, String)>,
}
assert_eq!(
"error: invalid value 'key_without_value' for '--vars <VARS>...': should be formatted as key=value pair: `key_without_value`\n\nFor more information, try '--help'.\n",
Args::try_parse_from(["test", "--vars", "key_without_value"])
.err()
.unwrap()
.to_string()
);
}
}