Repository: djc/askama
Pull request #270 (2019-10-28 12:24:33)

Moved no-receiver size_hint method to a separate trait

djc: In this one, why isn't `extension()` causing problems? Is it because of the `Sized` bound?
jbg: Yes. I could move that into the other trait too (and rename the new trait) if desired.
jbg: (and in that case the Sized bound would no longer be needed)
djc: So as an alternative, could we add a `Sized` bound for `size_hint()`, as well?
jbg: It works, but you have to also add a `Self: Sized` bound to `render()`. PR: #271

Patch:
diff --git a/askama/src/lib.rs b/askama/src/lib.rs
index 498d204..000acc1 100644
--- a/askama/src/lib.rs
+++ b/askama/src/lib.rs
@@ -492,16 +492,21 @@ pub use askama_escape::{Html, Text};
 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());
+        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 dyn std::fmt::Write) -> Result<()>;
     /// Helper function to inspect the template's extension
-    fn extension() -> Option<&'static str>
-    where
-        Self: Sized;
+    fn extension(&self) -> Option<&'static str>;
+    /// Provides an conservative estimate of the expanded length of the rendered template
+    fn size_hint(&self) -> usize;
+}
+
+pub trait SizedTemplate {
+    /// Helper function to inspect the template's extension
+    fn extension() -> Option<&'static str>;
     /// Provides an conservative estimate of the expanded length of the rendered template
     fn size_hint() -> usize;
 }
diff --git a/askama_derive/src/generator.rs b/askama_derive/src/generator.rs
index 28b8246..359de5a 100644
--- a/askama_derive/src/generator.rs
+++ b/askama_derive/src/generator.rs
@@ -136,17 +136,32 @@ impl<'a> Generator<'a> {
         buf.writeln("Ok(())");
         buf.writeln("}");
 
-        buf.writeln("fn extension() -> Option<&'static str> {");
+        buf.writeln("fn extension(&self) -> Option<&'static str> {");
         buf.writeln(&format!(
             "{:?}",
             self.input.path.extension().map(|s| s.to_str().unwrap())
         ));
         buf.writeln("}");
 
+        buf.writeln("fn size_hint(&self) -> usize {");
+        buf.writeln(&format!("{}", size_hint));
+        buf.writeln("}");
+
+        buf.writeln("}");
+
+        self.write_header(buf, "::askama::SizedTemplate", None);
+
         buf.writeln("fn size_hint() -> usize {");
         buf.writeln(&format!("{}", size_hint));
         buf.writeln("}");
 
+        buf.writeln("fn extension() -> Option<&'static str> {");
+        buf.writeln(&format!(
+            "{:?}",
+            self.input.path.extension().map(|s| s.to_str().unwrap())
+        ));
+        buf.writeln("}");
+
         buf.writeln("}");
     }
 


Test patch:
diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs
index 519b87c..168644a 100644
--- a/testing/tests/simple.rs
+++ b/testing/tests/simple.rs
@@ -1,4 +1,4 @@
-use askama::Template;
+use askama::{SizedTemplate, Template};
 
 use std::collections::HashMap;
 
@@ -24,7 +24,7 @@ fn test_variables() {
          Iñtërnâtiônàlizætiøn is important\n\
          in vars too: Iñtërnâtiônàlizætiøn"
     );
-    assert_eq!(VariablesTemplate::extension(), Some("html"));
+    assert_eq!(<VariablesTemplate as SizedTemplate>::extension(), Some("html"));
 }
 
 #[derive(Template)]