diff options
Diffstat (limited to 'askama_shared/src/lib.rs')
| -rw-r--r-- | askama_shared/src/lib.rs | 88 | 
1 files changed, 88 insertions, 0 deletions
| diff --git a/askama_shared/src/lib.rs b/askama_shared/src/lib.rs index 81500e1..b656c53 100644 --- a/askama_shared/src/lib.rs +++ b/askama_shared/src/lib.rs @@ -26,6 +26,72 @@ mod heritage;  mod input;  mod parser; +/// Main `Template` trait; implementations are generally derived +/// +/// If you need an object-safe template, use [`DynTemplate`]. +pub trait Template { +    /// Helper method which allocates a new `String` and renders into it +    fn render(&self) -> Result<String> { +        let mut buf = String::with_capacity(Self::SIZE_HINT); +        self.render_into(&mut buf)?; +        Ok(buf) +    } + +    /// Renders the template to the given `writer` buffer +    fn render_into(&self, writer: &mut (impl std::fmt::Write + ?Sized)) -> Result<()>; + +    /// The template's extension, if provided +    const EXTENSION: Option<&'static str>; + +    /// Provides a conservative estimate of the expanded length of the rendered template +    const SIZE_HINT: usize; + +    /// The MIME type (Content-Type) of the data that gets rendered by this Template +    const MIME_TYPE: &'static str; +} + +/// Object-safe wrapper trait around [`Template`] implementers +/// +/// This trades reduced performance (mostly due to writing into `dyn Write`) for object safety. +pub trait DynTemplate { +    /// Helper method which allocates a new `String` and renders into it +    fn dyn_render(&self) -> Result<String>; + +    /// Renders the template to the given `writer` buffer +    fn dyn_render_into(&self, writer: &mut dyn std::fmt::Write) -> Result<()>; + +    /// Helper function to inspect the template's extension +    fn extension(&self) -> Option<&'static str>; + +    /// Provides a conservative estimate of the expanded length of the rendered template +    fn size_hint(&self) -> usize; + +    /// The MIME type (Content-Type) of the data that gets rendered by this Template +    fn mime_type(&self) -> &'static str; +} + +impl<T: Template> DynTemplate for T { +    fn dyn_render(&self) -> Result<String> { +        <Self as Template>::render(self) +    } + +    fn dyn_render_into(&self, writer: &mut dyn std::fmt::Write) -> Result<()> { +        <Self as Template>::render_into(self, writer) +    } + +    fn extension(&self) -> Option<&'static str> { +        Self::EXTENSION +    } + +    fn size_hint(&self) -> usize { +        Self::SIZE_HINT +    } + +    fn mime_type(&self) -> &'static str { +        Self::MIME_TYPE +    } +} +  #[derive(Debug)]  struct Config<'a> {      dirs: Vec<PathBuf>, @@ -521,4 +587,26 @@ mod tests {              ]          );      } + +    #[test] +    fn dyn_template() { +        struct Test; +        impl Template for Test { +            fn render_into(&self, writer: &mut (impl std::fmt::Write + ?Sized)) -> Result<()> { +                Ok(writer.write_str("test")?) +            } + +            const EXTENSION: Option<&'static str> = Some("txt"); + +            const SIZE_HINT: usize = 4; + +            const MIME_TYPE: &'static str = "text/plain; charset=utf-8"; +        } + +        fn render(t: &dyn DynTemplate) -> String { +            t.dyn_render().unwrap() +        } + +        assert_eq!(render(&Test), "test"); +    }  } | 
