Add trim filter
This commit is contained in:
parent
31bbcaebc8
commit
fcde448751
|
@ -1,6 +1,9 @@
|
||||||
|
//! Build-in filters
|
||||||
|
|
||||||
// TODO: performance improvement
|
// TODO: performance improvement
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
use super::{Buffer, Render, RenderError};
|
use super::{Buffer, Render, RenderError};
|
||||||
|
|
||||||
|
@ -86,6 +89,60 @@ pub fn lower<T: Render>(expr: &T) -> Lower<T> {
|
||||||
Lower(expr)
|
Lower(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Trim<'a, T>(&'a T);
|
||||||
|
|
||||||
|
impl<'a, T: Render> Render for Trim<'a, T> {
|
||||||
|
#[inline]
|
||||||
|
fn render(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
||||||
|
let old_len = b.len();
|
||||||
|
self.0.render(b)?;
|
||||||
|
trim_impl(b, old_len);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn render_escaped(&self, b: &mut Buffer) -> Result<(), RenderError> {
|
||||||
|
let old_len = b.len();
|
||||||
|
self.0.render_escaped(b)?;
|
||||||
|
trim_impl(b, old_len);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trim_impl(b: &mut Buffer, old_len: usize) {
|
||||||
|
debug_assert!(b.len() >= old_len);
|
||||||
|
let new_contents = &b.as_str()[old_len..];
|
||||||
|
let trimmed = new_contents.trim();
|
||||||
|
let trimmed_len = trimmed.len();
|
||||||
|
|
||||||
|
if new_contents.len() != trimmed_len {
|
||||||
|
// performs inplace trimming
|
||||||
|
|
||||||
|
if new_contents.as_ptr() != trimmed.as_ptr() {
|
||||||
|
debug_assert!(new_contents.as_ptr() < trimmed.as_ptr());
|
||||||
|
let offset = trimmed.as_ptr() as usize - new_contents.as_ptr() as usize;
|
||||||
|
unsafe {
|
||||||
|
ptr::copy(
|
||||||
|
b.as_mut_ptr().add(old_len + offset),
|
||||||
|
b.as_mut_ptr().add(old_len),
|
||||||
|
trimmed_len,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(b.capacity() >= old_len + trimmed_len);
|
||||||
|
unsafe {
|
||||||
|
b._set_len(old_len + trimmed_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// convert the rendered contents to lowercase
|
||||||
|
#[inline]
|
||||||
|
pub fn trim<T: Render>(expr: &T) -> Trim<T> {
|
||||||
|
Trim(expr)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -104,4 +161,23 @@ mod tests {
|
||||||
lower(&"<h1>TITLE</h1>").render_escaped(&mut buf).unwrap();
|
lower(&"<h1>TITLE</h1>").render_escaped(&mut buf).unwrap();
|
||||||
assert_eq!(buf.as_str(), "<h1>title</h1>");
|
assert_eq!(buf.as_str(), "<h1>title</h1>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trim_test() {
|
||||||
|
let mut buf = Buffer::new();
|
||||||
|
trim(&" hello ").render(&mut buf).unwrap();
|
||||||
|
trim(&"hello ").render(&mut buf).unwrap();
|
||||||
|
trim(&" hello").render(&mut buf).unwrap();
|
||||||
|
assert_eq!(buf.as_str(), "hellohellohello");
|
||||||
|
|
||||||
|
let mut buf = Buffer::new();
|
||||||
|
trim(&"hello ").render(&mut buf).unwrap();
|
||||||
|
trim(&" hello").render(&mut buf).unwrap();
|
||||||
|
trim(&"hello").render(&mut buf).unwrap();
|
||||||
|
assert_eq!(buf.as_str(), "hellohellohello");
|
||||||
|
|
||||||
|
let mut buf = Buffer::new();
|
||||||
|
trim(&" hello").render(&mut buf).unwrap();
|
||||||
|
assert_eq!(buf.as_str(), "hello");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue