use crate::resource;
use crate::SubplotError;
use serde::Deserialize;
use std::path::{Path, PathBuf};
#[derive(Debug, Deserialize)]
pub struct TemplateSpec {
template: PathBuf,
#[serde(default)]
helpers: Vec<PathBuf>,
run: Option<String>,
}
impl TemplateSpec {
fn from_yaml(yaml: &str) -> Result<TemplateSpec, SubplotError> {
serde_yaml::from_str(yaml).map_err(SubplotError::Metadata)
}
fn new(
basedir: &Path,
template: &Path,
helpers: Vec<PathBuf>,
run: Option<&str>,
) -> TemplateSpec {
TemplateSpec {
template: basedir.to_path_buf().join(template),
helpers,
run: run.map(str::to_string),
}
}
pub fn from_file(filename: &Path) -> Result<TemplateSpec, SubplotError> {
let yaml = resource::read_as_string(filename, None)
.map_err(|err| SubplotError::ReadFile(filename.to_path_buf(), err))?;
let spec = TemplateSpec::from_yaml(&yaml)?;
let dirname = match filename.parent() {
Some(x) => x,
None => {
return Err(SubplotError::NoTemplateSpecDirectory(
filename.to_path_buf(),
))
}
};
Ok(TemplateSpec::new(
dirname,
spec.template_filename(),
spec.helpers().map(|p| p.to_path_buf()).collect(),
spec.run(),
))
}
pub fn template_filename(&self) -> &Path {
&self.template
}
pub fn helpers(&self) -> impl Iterator<Item = &Path> {
self.helpers.iter().map(|p| p.as_path())
}
pub fn run(&self) -> Option<&str> {
self.run.as_deref()
}
}
#[cfg(test)]
mod test {
use super::TemplateSpec;
#[test]
fn new_from_yaml() {
let yaml = "
template: template.py
";
let spec = TemplateSpec::from_yaml(yaml).unwrap();
assert_eq!(spec.template_filename().to_str().unwrap(), "template.py");
}
}