pretty_print/render/
write_fmt.rs

1use crate::{render::Annotation, Render, RenderAnnotated};
2use alloc::rc::Rc;
3use color_ansi::AnsiStyle;
4use core::fmt::{Debug, Formatter};
5
6/// Writes to something implementing `std::fmt::Write`
7pub struct FmtWrite<W> {
8    upstream: W,
9}
10/// Represents a terminal writer.
11#[derive(Debug)]
12pub struct BufferWrite {
13    buffer: String,
14    annotations: Vec<(usize, Annotation<AnsiStyle>)>,
15}
16
17impl BufferWrite {
18    /// Creates a new terminal writer.
19    pub fn new(capacity: usize) -> Self {
20        BufferWrite { buffer: String::with_capacity(capacity), annotations: Vec::new() }
21    }
22    /// Creates a new terminal writer.
23    pub fn render<W>(&mut self, render: &mut W) -> Result<(), W::Error>
24    where
25        W: RenderAnnotated,
26        W: ?Sized,
27    {
28        let mut start = 0;
29        for (end, annotation) in &self.annotations {
30            let s = &self.buffer[start..*end];
31            if !s.is_empty() {
32                render.write_str_all(s)?;
33            }
34            start = *end;
35            match annotation {
36                Annotation::Push(a) => render.push_annotation(a.clone())?,
37                Annotation::Pop => render.pop_annotation()?,
38            }
39        }
40        let s = &self.buffer[start..];
41        if !s.is_empty() {
42            render.write_str_all(s)?;
43        }
44        Ok(())
45    }
46}
47
48impl Render for BufferWrite {
49    type Error = core::fmt::Error;
50
51    fn write_str(&mut self, s: &str) -> Result<usize, Self::Error> {
52        self.buffer.push_str(s);
53        Ok(s.len())
54    }
55
56    fn write_str_all(&mut self, s: &str) -> Result<(), Self::Error> {
57        self.buffer.push_str(s);
58        Ok(())
59    }
60
61    fn fail_doc(&self) -> Self::Error {
62        core::fmt::Error::default()
63    }
64}
65
66impl<W> RenderAnnotated for FmtWrite<W>
67where
68    W: core::fmt::Write,
69{
70    fn push_annotation(&mut self, _: Rc<AnsiStyle>) -> Result<(), Self::Error> {
71        Ok(())
72    }
73
74    fn pop_annotation(&mut self) -> Result<(), Self::Error> {
75        Ok(())
76    }
77}
78
79impl RenderAnnotated for BufferWrite {
80    fn push_annotation(&mut self, annotation: Rc<AnsiStyle>) -> Result<(), Self::Error> {
81        self.annotations.push((self.buffer.len(), Annotation::Push(annotation)));
82        Ok(())
83    }
84
85    fn pop_annotation(&mut self) -> Result<(), Self::Error> {
86        self.annotations.push((self.buffer.len(), Annotation::Pop));
87        Ok(())
88    }
89}
90
91impl<W> Debug for FmtWrite<W> {
92    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93        f.debug_struct("IoWrite").finish()
94    }
95}
96
97impl<W> FmtWrite<W> {
98    /// Create a new `FmtWrite` from something implementing `std::fmt::Write`
99    pub fn new(upstream: W) -> FmtWrite<W> {
100        FmtWrite { upstream }
101    }
102}
103
104impl<W> Render for FmtWrite<W>
105where
106    W: core::fmt::Write,
107{
108    type Error = core::fmt::Error;
109
110    fn write_str(&mut self, s: &str) -> Result<usize, core::fmt::Error> {
111        self.write_str_all(s).map(|_| s.len())
112    }
113
114    fn write_str_all(&mut self, s: &str) -> core::fmt::Result {
115        self.upstream.write_str(s)
116    }
117
118    fn fail_doc(&self) -> Self::Error {
119        core::fmt::Error
120    }
121}