use super::{Part, Template, Variable};
use crate::error::{self, ExpandError};
use crate::VariableMap;
impl Template {
pub fn expand<'a, M, F>(
&self,
output: &mut Vec<u8>,
source: &[u8],
variables: &'a M,
to_bytes: &F,
) -> Result<(), ExpandError>
where
M: VariableMap<'a> + ?Sized,
F: Fn(&M::Value) -> &[u8],
{
for part in &self.parts {
match part {
Part::Literal(x) => output.extend_from_slice(&source[x.range.clone()]),
Part::EscapedByte(x) => output.push(x.value),
Part::Variable(x) => x.expand(output, source, variables, to_bytes)?,
}
}
Ok(())
}
}
impl Variable {
fn expand<'a, M, F>(
&self,
output: &mut Vec<u8>,
source: &[u8],
variables: &'a M,
to_bytes: &F,
) -> Result<(), ExpandError>
where
M: VariableMap<'a> + ?Sized,
F: Fn(&M::Value) -> &[u8],
{
let name = std::str::from_utf8(&source[self.name.clone()]).unwrap();
if let Some(value) = variables.get(name) {
output.extend_from_slice(to_bytes(&value));
Ok(())
} else if let Some(default) = &self.default {
default.expand(output, source, variables, to_bytes)
} else {
Err(ExpandError::NoSuchVariable(error::NoSuchVariable {
position: self.name.start,
name: name.to_owned(),
}))
}
}
}