Repository: lambda-fairy/maud
Pull request #361 (2022-11-25 14:33:20)

Bump axum-core to 0.3.0
This is required for axum 0.6 support


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48d5a1e..93c665d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
 
 - Remove `html_debug!`
   [#357](https://github.com/lambda-fairy/maud/pull/357)
+- Support `axum` v0.6 through `axum-core` v0.3
+  [#361](https://github.com/lambda-fairy/maud/pull/361)
 
 ## [0.24.0] - 2022-08-12
 
diff --git a/maud/Cargo.toml b/maud/Cargo.toml
index 4838b31..e96d5c4 100644
--- a/maud/Cargo.toml
+++ b/maud/Cargo.toml
@@ -25,7 +25,7 @@ rocket = { version = ">= 0.3, < 0.5", optional = true }
 futures-util = { version = "0.3.0", optional = true, default-features = false }
 actix-web-dep = { package = "actix-web", version = "4", optional = true, default-features = false }
 tide = { version = "0.16.0", optional = true, default-features = false }
-axum-core = { version = "0.2", optional = true }
+axum-core = { version = "0.3", optional = true }
 http = { version = "0.2", optional = true }
 
 [dev-dependencies]
diff --git a/maud/src/lib.rs b/maud/src/lib.rs
index a23c2b1..9c4a180 100644
--- a/maud/src/lib.rs
+++ b/maud/src/lib.rs
@@ -340,3 +340,54 @@ mod axum_support {
         }
     }
 }
+
+#[doc(hidden)]
+pub mod macro_private {
+    use crate::{display, Render};
+    use alloc::string::String;
+    use core::fmt::Display;
+
+    #[doc(hidden)]
+    #[macro_export]
+    macro_rules! render_to {
+        ($x:expr, $buffer:expr) => {{
+            use $crate::macro_private::*;
+            match ChooseRenderOrDisplay($x) {
+                x => (&&x).implements_render_or_display().render_to(x.0, $buffer),
+            }
+        }};
+    }
+
+    pub use render_to;
+
+    pub struct ChooseRenderOrDisplay<T>(pub T);
+
+    pub struct ViaRenderTag;
+    pub struct ViaDisplayTag;
+
+    pub trait ViaRender {
+        fn implements_render_or_display(&self) -> ViaRenderTag {
+            ViaRenderTag
+        }
+    }
+    pub trait ViaDisplay {
+        fn implements_render_or_display(&self) -> ViaDisplayTag {
+            ViaDisplayTag
+        }
+    }
+
+    impl<T: Render> ViaRender for &ChooseRenderOrDisplay<T> {}
+    impl<T: Display> ViaDisplay for ChooseRenderOrDisplay<T> {}
+
+    impl ViaRenderTag {
+        pub fn render_to<T: Render + ?Sized>(self, value: &T, buffer: &mut String) {
+            value.render_to(buffer);
+        }
+    }
+
+    impl ViaDisplayTag {
+        pub fn render_to<T: Display + ?Sized>(self, value: &T, buffer: &mut String) {
+            display(value).render_to(buffer);
+        }
+    }
+}
diff --git a/maud_macros/src/generate.rs b/maud_macros/src/generate.rs
index ad8a088..c9ba9fb 100644
--- a/maud_macros/src/generate.rs
+++ b/maud_macros/src/generate.rs
@@ -103,7 +103,7 @@ impl Generator {
 
     fn splice(&self, expr: TokenStream, build: &mut Builder) {
         let output_ident = self.output_ident.clone();
-        build.push_tokens(quote!(maud::Render::render_to(&#expr, &mut #output_ident);));
+        build.push_tokens(quote!(maud::macro_private::render_to!(&#expr, &mut #output_ident);));
     }
 
     fn element(&self, name: TokenStream, attrs: Vec<Attr>, body: ElementBody, build: &mut Builder) {


Test patch:
diff --git a/doctest/Cargo.toml b/doctest/Cargo.toml
index 53ec8ac..c55afcd 100644
--- a/doctest/Cargo.toml
+++ b/doctest/Cargo.toml
@@ -13,7 +13,7 @@ rocket = "0.4"
 rouille = "3"
 tide = "0.16"
 tokio = { version = "1.9.0", features = ["rt", "macros", "rt-multi-thread"] }
-axum = "0.5"
+axum = "0.6"
 
 [dependencies.async-std]
 version = "1.9.0"
diff --git a/maud/tests/misc.rs b/maud/tests/misc.rs
index 741af42..b9aae52 100644
--- a/maud/tests/misc.rs
+++ b/maud/tests/misc.rs
@@ -83,3 +83,50 @@ fn issue_97() {
 
     assert_eq!(html! { (Pinkie) }.into_string(), "42");
 }
+
+#[test]
+fn only_display() {
+    use core::fmt::Display;
+
+    struct OnlyDisplay;
+    impl Display for OnlyDisplay {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "<hello>")
+        }
+    }
+
+    assert_eq!(html! { (OnlyDisplay) }.into_string(), "&lt;hello&gt;");
+    assert_eq!(html! { (&OnlyDisplay) }.into_string(), "&lt;hello&gt;");
+    assert_eq!(html! { (&&OnlyDisplay) }.into_string(), "&lt;hello&gt;");
+    assert_eq!(html! { (&&&OnlyDisplay) }.into_string(), "&lt;hello&gt;");
+    assert_eq!(html! { (&&&&OnlyDisplay) }.into_string(), "&lt;hello&gt;");
+}
+
+#[test]
+fn prefer_render_over_display() {
+    use core::fmt::Display;
+    use maud::Render;
+
+    struct RenderAndDisplay;
+    impl Display for RenderAndDisplay {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "<display>")
+        }
+    }
+    impl Render for RenderAndDisplay {
+        fn render_to(&self, buffer: &mut String) {
+            buffer.push_str("<render>");
+        }
+    }
+
+    assert_eq!(html! { (RenderAndDisplay) }.into_string(), "<render>");
+    assert_eq!(html! { (&RenderAndDisplay) }.into_string(), "<render>");
+    assert_eq!(html! { (&&RenderAndDisplay) }.into_string(), "<render>");
+    assert_eq!(html! { (&&&RenderAndDisplay) }.into_string(), "<render>");
+    assert_eq!(html! { (&&&&RenderAndDisplay) }.into_string(), "<render>");
+
+    assert_eq!(
+        html! { (maud::display(RenderAndDisplay)) }.into_string(),
+        "&lt;display&gt;"
+    );
+}