use std::{
borrow::Cow,
collections::HashMap,
fs,
hash::Hash,
path::{Path, PathBuf},
};
pub trait SourceProvider {
type Key: Clone + Hash + PartialEq + Eq;
fn get_src(&mut self, key: &Self::Key) -> Result<String, Cow<'static, str>>;
fn resolve_partial(&self, key: &Self::Key, name: &str) -> Self::Key;
fn display_key(key: &'_ Self::Key) -> Cow<'_, str>;
}
pub struct FsProvider;
impl SourceProvider for FsProvider {
type Key = PathBuf;
fn get_src(&mut self, key: &Self::Key) -> Result<String, Cow<'static, str>> {
fs::read_to_string(key)
.map_err(|_| format!("cannot read file {}", key.to_string_lossy()).into())
}
fn resolve_partial(&self, key: &Self::Key, name: &str) -> Self::Key {
let mut key = key.parent().map_or_else(PathBuf::default, Path::to_owned);
key.push(name);
key.set_extension("mustache");
key
}
fn display_key(key: &'_ Self::Key) -> Cow<'_, str> {
key.to_string_lossy()
}
}
pub struct StaticProvider(pub HashMap<&'static str, &'static str>);
impl SourceProvider for StaticProvider {
type Key = &'static str;
fn get_src(&mut self, key: &Self::Key) -> Result<String, std::borrow::Cow<'static, str>> {
self.0
.get(key)
.cloned()
.map(String::from)
.ok_or("unknown partial".into())
}
fn resolve_partial(&self, _: &Self::Key, name: &str) -> Self::Key {
if let Some((k, _)) = self.0.get_key_value(name) {
*k
} else {
name.to_string().leak()
}
}
fn display_key(key: &'_ Self::Key) -> Cow<'_, str> {
Cow::Borrowed(*key)
}
}
#[cfg(feature = "ext-lambdas")]
pub(super) struct LambdaSourceProvider(pub Option<String>);
#[cfg(feature = "ext-lambdas")]
impl SourceProvider for LambdaSourceProvider {
type Key = ();
fn get_src(&mut self, (): &Self::Key) -> Result<String, std::borrow::Cow<'static, str>> {
self.0
.take()
.ok_or("partials are not allowed inside lambdas".into())
}
fn resolve_partial(&self, (): &Self::Key, _: &str) -> Self::Key {
()
}
fn display_key((): &'_ Self::Key) -> Cow<'_, str> {
Cow::Borrowed("<λ source>")
}
}