use std::io::{Error as IOError, Write}; use std::string::FromUtf8Error; /// The Output API. /// /// Handlebars uses this trait to define rendered output. pub trait Output { fn write(&mut self, seg: &str) -> Result<(), IOError>; /// Designed to be used with `write!` macro. /// for backward compatibility and to avoid breakage the default implementation /// uses `format!` this may be not what you want. fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), IOError> { // Check if there is nothing to format to avoid allocation on case like // write!(out, "hey")?; if let Some(content) = args.as_str() { self.write(content) } else { self.write(&std::fmt::format(args)) } } } pub struct WriteOutput { write: W, } impl Output for WriteOutput { fn write(&mut self, seg: &str) -> Result<(), IOError> { self.write.write_all(seg.as_bytes()) } fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), IOError> { self.write.write_fmt(args) } } impl WriteOutput { pub fn new(write: W) -> WriteOutput { WriteOutput { write } } } pub struct StringOutput { buf: Vec, } impl Output for StringOutput { fn write(&mut self, seg: &str) -> Result<(), IOError> { self.buf.extend_from_slice(seg.as_bytes()); Ok(()) } fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), IOError> { self.buf.write_fmt(args) } } impl StringOutput { pub fn new() -> StringOutput { StringOutput { buf: Vec::with_capacity(8 * 1024), } } pub fn into_string(self) -> Result { String::from_utf8(self.buf) } } impl Default for StringOutput { fn default() -> Self { StringOutput::new() } }