diff options
author | Cole Faust <colecfaust@gmail.com> | 2024-01-21 21:22:15 -0800 |
---|---|---|
committer | Evan Martin <evan.martin@gmail.com> | 2024-01-25 00:30:16 -0800 |
commit | a0e37e96a75f373bd85de0ffda324a8a64f4f6cb (patch) | |
tree | 0a1a9d218ef8312629b4e00298eb06cdbcee629d | |
parent | c90437e5024789e90b221589dff73f2997f91532 (diff) | |
download | n2-a0e37e96a75f373bd85de0ffda324a8a64f4f6cb.tar.gz |
Precalcuate length of evaluated strings
So that we can do one memory allocation for them.
-rw-r--r-- | src/eval.rs | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/eval.rs b/src/eval.rs index 5adf6ce..4b711c5 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -47,6 +47,23 @@ impl<T: AsRef<str>> EvalString<T> { } } + fn calc_evaluated_length(&self, envs: &[&dyn Env]) -> usize { + self.0 + .iter() + .map(|part| match part { + EvalPart::Literal(s) => s.as_ref().len(), + EvalPart::VarRef(v) => { + for (i, env) in envs.iter().enumerate() { + if let Some(v) = env.get_var(v.as_ref()) { + return v.calc_evaluated_length(&envs[i + 1..]); + } + } + 0 + } + }) + .sum() + } + /// evalulate turns the EvalString into a regular String, looking up the /// values of variable references in the provided Envs. It will look up /// its variables in the earliest Env that has them, and then those lookups @@ -54,6 +71,7 @@ impl<T: AsRef<str>> EvalString<T> { /// had the first successful lookup. pub fn evaluate(&self, envs: &[&dyn Env]) -> String { let mut result = String::new(); + result.reserve(self.calc_evaluated_length(envs)); self.evaluate_inner(&mut result, envs); result } |