handlebars/
output.rs

1use std::io::{Error as IOError, Write};
2use std::string::FromUtf8Error;
3
4/// The Output API.
5///
6/// Handlebars uses this trait to define rendered output.
7pub trait Output {
8    fn write(&mut self, seg: &str) -> Result<(), IOError>;
9
10    /// Designed to be used with `write!` macro.
11    /// for backward compatibility and to avoid breakage the default implementation
12    /// uses `format!` this may be not what you want.
13    fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), IOError> {
14        // Check if there is nothing to format to avoid allocation on case like
15        // write!(out, "hey")?;
16        if let Some(content) = args.as_str() {
17            self.write(content)
18        } else {
19            self.write(&std::fmt::format(args))
20        }
21    }
22}
23
24pub struct WriteOutput<W: Write> {
25    write: W,
26}
27
28impl<W: Write> Output for WriteOutput<W> {
29    fn write(&mut self, seg: &str) -> Result<(), IOError> {
30        self.write.write_all(seg.as_bytes())
31    }
32
33    fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), IOError> {
34        self.write.write_fmt(args)
35    }
36}
37
38impl<W: Write> WriteOutput<W> {
39    pub fn new(write: W) -> WriteOutput<W> {
40        WriteOutput { write }
41    }
42}
43
44pub struct StringOutput {
45    buf: Vec<u8>,
46}
47
48impl Output for StringOutput {
49    fn write(&mut self, seg: &str) -> Result<(), IOError> {
50        self.buf.extend_from_slice(seg.as_bytes());
51        Ok(())
52    }
53
54    fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> Result<(), IOError> {
55        self.buf.write_fmt(args)
56    }
57}
58
59impl StringOutput {
60    pub fn new() -> StringOutput {
61        StringOutput {
62            buf: Vec::with_capacity(8 * 1024),
63        }
64    }
65
66    pub fn into_string(self) -> Result<String, FromUtf8Error> {
67        String::from_utf8(self.buf)
68    }
69}
70
71impl Default for StringOutput {
72    fn default() -> Self {
73        StringOutput::new()
74    }
75}