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: &str) = args.as_str() {
17 self.write(seg: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(buf: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}
76