feat(runtime): add portable runtime support
req: push/009 req: push/010 req: push/011
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
[package]
|
||||
name = "hemplate-runtime"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
publish = false
|
||||
@@ -0,0 +1,131 @@
|
||||
use std::fmt;
|
||||
|
||||
pub mod error {
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HemplateError;
|
||||
|
||||
impl fmt::Display for HemplateError {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("hemplate rendering failed")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for HemplateError {}
|
||||
|
||||
impl From<fmt::Error> for HemplateError {
|
||||
fn from(_: fmt::Error) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Hemplate {
|
||||
fn render_into(&self, buffer: &mut String) -> Result<(), error::HemplateError>;
|
||||
|
||||
fn render(&self) -> String {
|
||||
let mut buffer = String::new();
|
||||
self.render_into(&mut buffer)
|
||||
.expect("writing a hemplate String cannot fail");
|
||||
buffer
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render<T: Hemplate + ?Sized>(value: &T) -> Result<String, error::HemplateError> {
|
||||
let mut buffer = String::new();
|
||||
value.render_into(&mut buffer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
struct HtmlEscape<T: fmt::Display>(T);
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for HtmlEscape<T> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for character in self.0.to_string().chars() {
|
||||
match character {
|
||||
'&' => formatter.write_str("&")?,
|
||||
'<' => formatter.write_str("<")?,
|
||||
'>' => formatter.write_str(">")?,
|
||||
'"' => formatter.write_str(""")?,
|
||||
'\'' => formatter.write_str("'")?,
|
||||
other => fmt::Write::write_char(formatter, other)?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod render {
|
||||
use super::{error::HemplateError, Hemplate, HtmlEscape};
|
||||
use std::fmt;
|
||||
|
||||
pub struct Escaped<'a, T: ?Sized>(pub &'a T);
|
||||
|
||||
impl<T: Hemplate + ?Sized> Escaped<'_, T> {
|
||||
pub fn render_to(&self, buffer: &mut String) -> Result<(), HemplateError> {
|
||||
self.0.render_into(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EscapedFallback {
|
||||
fn render_to(&self, buffer: &mut String) -> Result<(), HemplateError>;
|
||||
}
|
||||
|
||||
impl<T: fmt::Display + ?Sized> EscapedFallback for Escaped<'_, T> {
|
||||
fn render_to(&self, buffer: &mut String) -> Result<(), HemplateError> {
|
||||
use fmt::Write;
|
||||
write!(buffer, "{}", HtmlEscape(self.0))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Raw<'a, T: ?Sized>(pub &'a T);
|
||||
|
||||
impl<T: Hemplate + ?Sized> Raw<'_, T> {
|
||||
pub fn render_to(&self, _buffer: &mut String) -> Result<(), HemplateError> {
|
||||
panic!("hemplate: raw interpolation must not be used with Hemplate types")
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RawFallback {
|
||||
fn render_to(&self, buffer: &mut String) -> Result<(), HemplateError>;
|
||||
}
|
||||
|
||||
impl<T: fmt::Display + ?Sized> RawFallback for Raw<'_, T> {
|
||||
fn render_to(&self, buffer: &mut String) -> Result<(), HemplateError> {
|
||||
use fmt::Write;
|
||||
write!(buffer, "{}", self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RawGuard<'a, T: ?Sized>(pub &'a T);
|
||||
pub struct RawInterpolationNotAllowedForHemplateTypes;
|
||||
|
||||
impl<T: Hemplate + ?Sized> RawGuard<'_, T> {
|
||||
pub fn check(&self) -> RawInterpolationNotAllowedForHemplateTypes {
|
||||
RawInterpolationNotAllowedForHemplateTypes
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RawGuardFallback {
|
||||
fn check(&self);
|
||||
}
|
||||
|
||||
impl<T: fmt::Display + ?Sized> RawGuardFallback for RawGuard<'_, T> {
|
||||
fn check(&self) {}
|
||||
}
|
||||
|
||||
impl<T: Hemplate + ?Sized> Hemplate for &T {
|
||||
fn render_into(&self, buffer: &mut String) -> Result<(), HemplateError> {
|
||||
(*self).render_into(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hemplate + ?Sized> Hemplate for Box<T> {
|
||||
fn render_into(&self, buffer: &mut String) -> Result<(), HemplateError> {
|
||||
(**self).render_into(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user