254 lines
6.5 KiB
Rust
254 lines
6.5 KiB
Rust
use std::path::{Path, PathBuf};
|
|
|
|
use super::buffer::Buffer;
|
|
use super::{escape, RenderError};
|
|
|
|
/// types which can be rendered inside buffer block (`<%= %>`)
|
|
pub trait Render {
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError>;
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
let mut tmp = Buffer::new();
|
|
self.render(&mut tmp)?;
|
|
b.push_str(tmp.as_str());
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
// /// Autoref-based stable specialization
|
|
// ///
|
|
// /// Explanation can be found [here](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md)
|
|
// impl<T: Display> Render for &T {
|
|
// fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// fmt::write(b, format_args!("{}", self))
|
|
// }
|
|
//
|
|
// fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// struct Wrapper<'a>(&'a mut Buffer);
|
|
//
|
|
// impl<'a> fmt::Write for Wrapper<'a> {
|
|
// #[inline]
|
|
// fn push_str(&mut self, s: &str) -> Result<(), RenderError> {
|
|
// escape::escape_to_buf(s, self.0);
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
//
|
|
// fmt::write(&mut Wrapper(b), format_args!("{}", self))
|
|
// }
|
|
// }
|
|
|
|
impl Render for str {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
b.push_str(self);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
escape::escape_to_buf(self, b);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<'a> Render for &'a str {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
b.push_str(self);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// escape string
|
|
escape::escape_to_buf(self, b);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Render for String {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
b.push_str(self);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// escape string
|
|
escape::escape_to_buf(self, b);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Render for char {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
b.push(*self);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
match *self {
|
|
'\"' => b.push_str("""),
|
|
'&' => b.push_str("&"),
|
|
'<' => b.push_str("<"),
|
|
'>' => b.push_str(">"),
|
|
_ => b.push(*self),
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<'a> Render for &'a Path {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// TODO: speed up on Windows using OsStrExt
|
|
b.push_str(&*self.to_string_lossy());
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
escape::escape_to_buf(&*self.to_string_lossy(), b);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Render for PathBuf {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
b.push_str(&*self.to_string_lossy());
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// escape string
|
|
escape::escape_to_buf(&*self.to_string_lossy(), b);
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
// impl Render for [u8] {
|
|
// #[inline]
|
|
// fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// b.write_bytes(self);
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
//
|
|
// impl<'a> Render for &'a [u8] {
|
|
// #[inline]
|
|
// fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// b.write_bytes(self);
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
//
|
|
// impl Render for Vec<u8> {
|
|
// #[inline]
|
|
// fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// b.write_bytes(&**self);
|
|
// Ok(())
|
|
// }
|
|
// }
|
|
|
|
impl Render for bool {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
let s = if *self { "true" } else { "false" };
|
|
b.push_str(s);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
self.render(b)
|
|
}
|
|
}
|
|
|
|
macro_rules! render_int {
|
|
($($int:ty),*) => {
|
|
$(
|
|
impl Render for $int {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
let mut buffer = itoa::Buffer::new();
|
|
let s = buffer.format(*self);
|
|
b.push_str(s);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// push_str without escape
|
|
self.render(b)
|
|
}
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
render_int!(u8, u16, u32, u64, i8, i16, i32, i64, usize, isize);
|
|
|
|
macro_rules! render_float {
|
|
($($float:ty),*) => {
|
|
$(
|
|
impl Render for $float {
|
|
#[inline]
|
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
let mut buffer = ryu::Buffer::new();
|
|
let s = buffer.format(*self);
|
|
b.push_str(s);
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
|
// escape string
|
|
self.render(b)
|
|
}
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
render_float!(f32, f64);
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn receiver_coercion() {
|
|
let mut b = Buffer::new();
|
|
(&1).render(&mut b).unwrap();
|
|
(&&1).render(&mut b).unwrap();
|
|
(&&&1).render(&mut b).unwrap();
|
|
(&&&&1).render(&mut b).unwrap();
|
|
|
|
let v = 2.0;
|
|
(&v).render(&mut b).unwrap();
|
|
(&&v).render(&mut b).unwrap();
|
|
(&&&v).render(&mut b).unwrap();
|
|
(&&&&v).render(&mut b).unwrap();
|
|
|
|
let s = "apple";
|
|
(&*s).render_escaped(&mut b).unwrap();
|
|
(&s).render_escaped(&mut b).unwrap();
|
|
(&&s).render_escaped(&mut b).unwrap();
|
|
(&&&s).render_escaped(&mut b).unwrap();
|
|
(&&&&s).render_escaped(&mut b).unwrap();
|
|
|
|
(&'c').render_escaped(&mut b).unwrap();
|
|
(&&'<').render_escaped(&mut b).unwrap();
|
|
(&&&'&').render_escaped(&mut b).unwrap();
|
|
(&&&&' ').render_escaped(&mut b).unwrap();
|
|
}
|
|
}
|