use tap::{Pipe, Tap};
use tinyvec::TinyVec;
use crate::{
MiniStr,
error::{ResolverError, ResolverResult},
parsers::context::Context,
resolver::{BTreeRawMap, TemplateResolver},
template::Template,
};
impl TemplateResolver {
pub fn get_with_context(
&self,
var_name: &str,
context: &[(&str, &str)],
) -> ResolverResult<MiniStr> {
let process = |ctx| self.try_get_template_and_process(var_name, ctx);
match context.is_empty() {
true => return process(&Context::Empty),
_ => context
.iter()
.copied()
.collect::<TinyVec<[(&str, &str); 5]>>()
.tap_mut(|x| x.sort_unstable_by_key(|&(k, _)| k)),
}
.as_ref()
.pipe(Context::Slice)
.pipe_ref(process)
}
pub fn get_with_ctx_btree_map(
&self,
var_name: &str,
context_map: &BTreeRawMap,
) -> ResolverResult<MiniStr> {
let process = |ctx| self.try_get_template_and_process(var_name, ctx);
match context_map.is_empty() {
true => Context::Empty,
_ => context_map.pipe(Context::BTree),
}
.pipe_ref(process)
}
pub fn try_get(&self, var_name: &str) -> ResolverResult<MiniStr> {
let process = |ctx| self.try_get_template_and_process(var_name, ctx);
process(&Context::Empty)
}
#[cfg(feature = "std")]
pub fn get_with_ctx_map(
&self,
var_name: &str,
context_map: &crate::ContextMap,
) -> ResolverResult<MiniStr> {
let process = |ctx| self.try_get_template_and_process(var_name, ctx);
match context_map.is_empty() {
true => Context::Empty,
_ => context_map.pipe(Context::Map),
}
.pipe_ref(process)
}
#[cfg(feature = "std")]
pub fn get_with_ctx_map_buf(
&self,
var_name: &str,
context_map: &crate::ContextMapBuf,
) -> ResolverResult<MiniStr> {
let process = |ctx| self.try_get_template_and_process(var_name, ctx);
match context_map.is_empty() {
true => Context::Empty,
_ => context_map.pipe(Context::MapBuf),
}
.pipe_ref(process)
}
pub(crate) fn try_get_template(&self, key: &str) -> ResolverResult<&Template> {
self
.0
.get(key)
.ok_or_else(|| ResolverError::UndefinedVariable(key.into()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
#[cfg(feature = "std")]
fn test_get_with_ctx_map() -> ResolverResult<()> {
let res: TemplateResolver = [
("g", "Good"),
("greeting", "{g} { time-period }! { $name }"),
(
"time-period",
"$period ->
[morning] Morning
*[other] {$period}",
),
]
.try_into()?;
let ctx_map = [("name", "Tom"), ("period", "night")]
.into_iter()
.collect();
let text = res.get_with_ctx_map("greeting", &ctx_map)?;
assert_eq!(text, "Good night! Tom");
Ok(())
}
#[test]
fn test_get_with_btree_map() -> ResolverResult<()> {
let res: TemplateResolver = [
("greeting", "Good { time-period }! { $name }"),
(
"time-period",
"$period ->
[morning] Morning
*[other] {$period}",
),
]
.try_into()?;
let ctx_map = [("name", "Tom"), ("period", "morning")]
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect();
let text = res.get_with_ctx_btree_map("greeting", &ctx_map)?;
assert_eq!(text, "Good Morning! Tom");
Ok(())
}
}