From 1fba1b76ec005fefa76b8585c95a075bd7cfc5c2 Mon Sep 17 00:00:00 2001 From: Agustin Chiappe Berrini <jnieve@gmail.com> Date: Sat, 18 Nov 2017 09:41:40 -0500 Subject: [PATCH] Reduce number of heap allocations --- src/parser/shell_expand/mod.rs | 43 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/parser/shell_expand/mod.rs b/src/parser/shell_expand/mod.rs index f16a4dfb..aa9171c5 100644 --- a/src/parser/shell_expand/mod.rs +++ b/src/parser/shell_expand/mod.rs @@ -50,15 +50,24 @@ fn expand_process<E: Expander>( }; slice(current, output, selection) } else { - // TODO: Complete this so that we don't need any heap allocations. - // All that we need is to shift bytes to the left when extra spaces are found. - // - // unsafe { - // let bytes: &mut [u8] = output.as_bytes_mut(); - // bytes.iter_mut().filter(|b| **b == b'\n').for_each(|b| *b = b' '); - // slice(current, str::from_utf8_unchecked(&bytes).trim(), selection) - // } - slice(current, &output.split_whitespace().collect::<Vec<&str>>().join(" "), selection) + let mut result = String::with_capacity(output.len()); + let mut previous_char_was_whitespace = true; + output + .chars() + .for_each(|c| { + match c { + c if !char::is_whitespace(c) => { + result.push(c); + previous_char_was_whitespace = false; + }, + c if char::is_whitespace(c) && !previous_char_was_whitespace => { + result.push(' '); + previous_char_was_whitespace = true; + }, + _ => (), + } + }); + slice(current, result.trim_right(), selection) } } } @@ -559,6 +568,22 @@ mod test { } } + struct CommandExpander; + + impl Expander for CommandExpander { + fn command(&self, cmd: &str) -> Option<Value> { + Some(cmd.to_owned()) + } + } + + #[test] + fn expand_process_unquoted() { + let mut output = String::new(); + let line = " Mary had\ta\u{2009}little \n\t lamb\t"; + expand_process(&mut output, line, Select::All, &CommandExpander, false); + assert_eq!(output, "Mary had a little lamb"); + } + #[test] fn expand_variable_normal_variable() { let input = "$FOO:NOT:$BAR"; -- GitLab