Skip to content

Commit

Permalink
Move Template into askama_shared, too
Browse files Browse the repository at this point in the history
The traits Template and DynTemplate need to be in sync with
askama_shared's generator. #647 consolidated the template crating into
askama_shared, this PR moves the trait itself.
  • Loading branch information
Kijewski authored and djc committed Mar 30, 2022
1 parent 799495b commit e30ce83
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 101 deletions.
105 changes: 4 additions & 101 deletions askama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,78 +63,11 @@
#![deny(elided_lifetimes_in_paths)]
#![deny(unreachable_pub)]

pub use askama_shared as shared;

pub use askama_escape::{Html, Text};

/// 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
}
}

pub use crate::shared::{filters, helpers, Error, MarkupDisplay, Result};
pub use askama_derive::*;
pub use askama_escape::{Html, Text};
pub use askama_shared::{
self as shared, filters, helpers, DynTemplate, Error, MarkupDisplay, Result, Template,
};

#[deprecated(since = "0.11.1", note = "The only function in this mod is deprecated")]
pub mod mime {
Expand All @@ -151,33 +84,3 @@ pub mod mime {
note = "file-level dependency tracking is handled automatically without build script"
)]
pub fn rerun_if_templates_changed() {}

#[cfg(test)]
mod tests {
use super::{DynTemplate, Template};

#[test]
fn dyn_template() {
struct Test;
impl Template for Test {
fn render_into(
&self,
writer: &mut (impl std::fmt::Write + ?Sized),
) -> askama_shared::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");
}
}
88 changes: 88 additions & 0 deletions askama_shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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");
}
}

0 comments on commit e30ce83

Please sign in to comment.