1use std::collections::HashMap;
4
5use crate::result::MapmErr::*;
6use crate::result::MapmResult;
7
8use std::fs;
9use std::path::Path;
10
11use serde::{Deserialize, Serialize};
12
13pub struct Template {
14 pub name: String,
15 pub engine: String,
16 pub texfiles: HashMap<String, String>,
18 pub problem_count: Option<usize>,
19 pub choices: Option<usize>,
24 pub vars: Vec<String>,
26 pub problemvars: Vec<String>,
28 pub solutionvars: Vec<String>,
30}
31
32#[derive(Debug, Serialize, Deserialize, Clone)]
33struct SerializedTemplate {
34 engine: String,
35 texfiles: HashMap<String, String>,
36 problem_count: Option<usize>,
37 choices: Option<usize>,
38 vars: Vec<String>,
39 problemvars: Vec<String>,
40 solutionvars: Vec<String>,
41}
42
43pub fn fetch_template_config<T: AsRef<Path>>(
46 template_name: &str,
47 templates_dir: T,
48) -> MapmResult<Template> {
49 let templates_dir: &Path = templates_dir.as_ref();
50 let template_path = &templates_dir.join(template_name).join("config.yml");
51 match fs::read_to_string(template_path) {
52 Ok(template_yaml) => parse_template_yaml(template_name, &template_yaml),
53 Err(_) => Err(TemplateErr(format!(
54 "Could not read template `{}` from {:?}",
55 template_name, template_path,
56 ))),
57 }
58}
59
60fn parse_template_yaml(name: &str, yaml: &str) -> MapmResult<Template> {
61 match serde_yaml::from_str::<SerializedTemplate>(yaml) {
62 Ok(template) => Ok(Template {
63 name: String::from(name),
64 engine: template.engine,
65 texfiles: template.texfiles,
66 problem_count: template.problem_count,
67 choices: template.choices,
68 vars: template.vars,
69 problemvars: template.problemvars,
70 solutionvars: template.solutionvars,
71 }),
72 Err(err) => Err(TemplateErr(err.to_string())),
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 #[test]
79 fn test_parse() {
80 use super::parse_template_yaml;
81 use std::collections::HashMap;
82
83 let template_yaml = r#"engine: pdflatex
84texfiles:
85 problems.tex: "${title}.PDF"
86 solutions.tex: "${title}-sols.PDF"
87problem_count: 1
88vars:
89 - title
90 - year
91problemvars:
92 - problem
93solutionvars:
94 - text
95 - author
96"#;
97
98 let template = parse_template_yaml("template", template_yaml).unwrap();
99
100 let mut texfiles = HashMap::new();
101 texfiles.insert(String::from("problems.tex"), String::from("${title}.PDF"));
102 texfiles.insert(
103 String::from("solutions.tex"),
104 String::from("${title}-sols.PDF"),
105 );
106
107 assert_eq!(template.name, "template");
108 assert_eq!(template.engine, "pdflatex");
109 assert_eq!(template.texfiles, texfiles);
110 assert_eq!(
111 template.vars,
112 vec![String::from("title"), String::from("year")]
113 );
114 assert_eq!(template.problemvars, vec![String::from("problem")]);
115 assert_eq!(
116 template.solutionvars,
117 vec![String::from("text"), String::from("author")]
118 );
119 }
120}