archetect_core/
rendering.rs

1use crate::vendor::tera::Context;
2use crate::{Archetect, RenderError};
3use std::path::{Path, PathBuf};
4
5pub trait Renderable {
6    type Result;
7
8    fn render(&self, archetect: &mut Archetect, context: &Context) -> Result<Self::Result, RenderError>;
9}
10
11impl Renderable for &str {
12    type Result = String;
13
14    fn render(&self, archetect: &mut Archetect, context: &Context) -> Result<Self::Result, RenderError> {
15        archetect.render_string(&self, context)
16    }
17}
18
19impl Renderable for &String {
20    type Result = String;
21
22    fn render(&self, archetect: &mut Archetect, context: &Context) -> Result<Self::Result, RenderError> {
23        archetect.render_string(&self, context)
24    }
25}
26
27impl Renderable for &Path {
28    type Result = PathBuf;
29
30    fn render(&self, archetect: &mut Archetect, context: &Context) -> Result<Self::Result, RenderError> {
31        if let Some(string) = self.to_str() {
32            match archetect.render_string(string, &context.clone()) {
33                Ok(result) => return Ok(PathBuf::from(result)),
34                Err(error) => {
35                    match error {
36                        RenderError::StringRenderError { string: _, source: error} => {
37
38                            return Err(RenderError::PathRenderError {
39                                path: self.into(),
40                                source: error,
41                            });
42                        }
43                        _ => panic!("Unexpected rendering error")
44                    }
45                }
46            }
47        } else {
48            return Err(RenderError::InvalidPathCharacters {
49                path: self.to_path_buf(),
50            });
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use crate::rendering::Renderable;
58    use crate::Archetect;
59    use std::path::{Path, PathBuf};
60    use crate::vendor::tera::Context;
61
62    #[test]
63    pub fn test_render_str_successfully() {
64        let mut archetect = Archetect::builder().build().unwrap();
65        let mut context = Context::new();
66        context.insert("subject", "world");
67
68        let render = "Hello, {{ subject }}".render(&mut archetect, &context).unwrap();
69        assert_eq!(render, "Hello, world".to_owned());
70    }
71
72    #[test]
73    pub fn test_render_path_successfully() {
74        let mut archetect = Archetect::builder().build().unwrap();
75        let mut context = Context::new();
76        context.insert("parent", "hello");
77        context.insert("child", "world");
78
79        let path = Path::new("{{ parent }}/{{ child }}");
80
81        let render = path.render(&mut archetect, &context).unwrap();
82        assert_eq!(render, PathBuf::from("hello/world"));
83    }
84
85    #[test]
86    pub fn test_render_empty_path() {
87        let archetect = &mut Archetect::builder().build().unwrap();
88        let mut context = Context::new();
89        context.insert("parent", "hello");
90        context.insert("child", "world");
91
92        let path = Path::new("");
93        let render = path.render(archetect, &context).unwrap();
94        assert_eq!(render, PathBuf::from(String::new()));
95    }
96}