mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-10-30 00:38:56 +00:00
Flat directory/module structure
This commit is contained in:
1 parent
d31936ec28
commit
30c381fe2a
27 files changed
+70
-71
No files matched your search
+115
@@ -0,0 +1,115 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
use super::types::ParameterValue;
|
||||
|
||||
/// A command that should be benchmarked.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Command<'a> {
|
||||
/// The command name (without parameter substitution)
|
||||
name: Option<&'a str>,
|
||||
|
||||
/// The command that should be executed (without parameter substitution)
|
||||
expression: &'a str,
|
||||
|
||||
/// Zero or more parameter values.
|
||||
parameters: Vec<(&'a str, ParameterValue)>,
|
||||
}
|
||||
|
||||
impl<'a> Command<'a> {
|
||||
pub fn new(name: Option<&'a str>, expression: &'a str) -> Command<'a> {
|
||||
Command {
|
||||
name,
|
||||
expression,
|
||||
parameters: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_parametrized(
|
||||
name: Option<&'a str>,
|
||||
expression: &'a str,
|
||||
parameters: Vec<(&'a str, ParameterValue)>,
|
||||
) -> Command<'a> {
|
||||
Command {
|
||||
name,
|
||||
expression,
|
||||
parameters,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_name(&self) -> String {
|
||||
self.name.map_or_else(
|
||||
|| self.get_shell_command(),
|
||||
|name| self.replace_parameters_in(name),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_shell_command(&self) -> String {
|
||||
self.replace_parameters_in(self.expression)
|
||||
}
|
||||
|
||||
pub fn get_parameters(&self) -> &Vec<(&'a str, ParameterValue)> {
|
||||
&self.parameters
|
||||
}
|
||||
|
||||
fn replace_parameters_in(&self, original: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let mut replacements = BTreeMap::<String, String>::new();
|
||||
for (param_name, param_value) in &self.parameters {
|
||||
replacements.insert(
|
||||
format!("{{{param_name}}}", param_name = param_name),
|
||||
param_value.to_string(),
|
||||
);
|
||||
}
|
||||
let mut remaining = original;
|
||||
// Manually replace consecutive occurrences to avoid double-replacing: e.g.,
|
||||
//
|
||||
// hyperfine -L foo 'a,{bar}' -L bar 'baz,quux' 'echo {foo} {bar}'
|
||||
//
|
||||
// should not ever run 'echo baz baz'. See `test_get_shell_command_nonoverlapping`.
|
||||
'outer: while let Some(head) = remaining.chars().next() {
|
||||
for (k, v) in &replacements {
|
||||
if remaining.starts_with(k.as_str()) {
|
||||
result.push_str(v);
|
||||
remaining = &remaining[k.len()..];
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
result.push(head);
|
||||
remaining = &remaining[head.len_utf8()..];
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_shell_command_nonoverlapping() {
|
||||
let cmd = Command::new_parametrized(
|
||||
None,
|
||||
"echo {foo} {bar}",
|
||||
vec![
|
||||
("foo", ParameterValue::Text("{bar} baz".into())),
|
||||
("bar", ParameterValue::Text("quux".into())),
|
||||
],
|
||||
);
|
||||
assert_eq!(cmd.get_shell_command(), "echo {bar} baz quux");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_parameterized_command_name() {
|
||||
let cmd = Command::new_parametrized(
|
||||
Some("name-{bar}-{foo}"),
|
||||
"echo {foo} {bar}",
|
||||
vec![
|
||||
("foo", ParameterValue::Text("baz".into())),
|
||||
("bar", ParameterValue::Text("quux".into())),
|
||||
],
|
||||
);
|
||||
assert_eq!(cmd.get_name(), "name-quux-baz");
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Command<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.get_shell_command())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user