by_loco/controller/views/
mod.rs1#[cfg(feature = "embedded_assets")]
3pub mod engine_embedded;
4#[cfg(feature = "embedded_assets")]
5pub use engine_embedded as engines;
6
7#[cfg(not(feature = "embedded_assets"))]
8pub mod engine;
9#[cfg(not(feature = "embedded_assets"))]
10pub use engine as engines;
11
12use axum::{extract::FromRequestParts, http::request::Parts, Extension};
13use serde::Serialize;
14pub mod tera_builtins;
15use crate::Result;
16
17#[cfg(feature = "with-db")]
18pub mod pagination;
19
20pub trait ViewRenderer {
21 fn render<S: Serialize>(&self, key: &str, data: S) -> Result<String>;
27}
28
29#[derive(Debug, PartialEq, Eq, Clone)]
30pub struct ViewEngine<E>(pub E);
31
32impl<E> ViewEngine<E> {
33 pub fn new(engine: E) -> Self {
35 Self(engine)
36 }
37}
38
39pub fn template<S>(template: &str, data: S) -> Result<String>
56where
57 S: Serialize,
58{
59 let mut tera = tera::Tera::default();
60 Ok(tera.render_str(template, &tera::Context::from_serialize(data)?)?)
61}
62
63impl<E> From<E> for ViewEngine<E> {
64 fn from(inner: E) -> Self {
65 Self::new(inner)
66 }
67}
68
69impl<S, E> FromRequestParts<S> for ViewEngine<E>
70where
71 S: Send + Sync,
72 E: Clone + Send + Sync + 'static,
73{
74 type Rejection = std::convert::Infallible;
75
76 async fn from_request_parts(
77 parts: &mut Parts,
78 state: &S,
79 ) -> std::result::Result<Self, Self::Rejection> {
80 let Extension(tl): Extension<Self> = Extension::from_request_parts(parts, state)
81 .await
82 .expect("TeraLayer missing. Is the TeraLayer installed?");
83 Ok(tl)
95 }
96}