use std::borrow::Cow;
use std::fmt;
use rkt::http::{ContentType, Status};
use rkt::request::{self, FromRequest};
use rkt::serde::Serialize;
use rkt::{Ignite, Request, Rocket, Sentinel};
use crate::{context::ContextManager, Template};
pub struct Metadata<'a>(&'a ContextManager);
impl Metadata<'_> {
pub fn contains_template(&self, name: &str) -> bool {
self.0.context().templates.contains_key(name)
}
pub fn reloading(&self) -> bool {
self.0.is_reloading()
}
pub fn render<S, C>(&self, name: S, context: C) -> Option<(ContentType, String)>
where
S: Into<Cow<'static, str>>,
C: Serialize,
{
Template::render(name.into(), context)
.finalize(&self.0.context())
.ok()
}
}
impl fmt::Debug for Metadata<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(&self.0.context().templates).finish()
}
}
impl Sentinel for Metadata<'_> {
fn abort(rocket: &Rocket<Ignite>) -> bool {
if rocket.state::<ContextManager>().is_none() {
error!(
"uninitialized template context: missing `Template::fairing()`.\n\
To use templates, you must attach `Template::fairing()`."
);
return true;
}
false
}
}
#[rkt::async_trait]
impl<'r> FromRequest<'r> for Metadata<'r> {
type Error = ();
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
request
.rocket()
.state::<ContextManager>()
.map(|cm| request::Outcome::Success(Metadata(cm)))
.unwrap_or_else(|| {
error!(
"uninitialized template context: missing `Template::fairing()`.\n\
To use templates, you must attach `Template::fairing()`."
);
request::Outcome::Error((Status::InternalServerError, ()))
})
}
}