Skip to main content

logparse_pretty_print/render/
write_io.rs

1#[cfg(feature = "std")]
2use crate::Text;
3use crate::{Render, RenderAnnotated};
4use alloc::rc::Rc;
5use color_ansi::{AnsiAbility, AnsiStyle, AnsiWriter};
6use core::fmt::{Debug, Formatter};
7
8#[cfg(feature = "std")]
9use std::io::{Error, Write};
10
11/// Represents a terminal writer.
12pub struct TerminalWriter<W> {
13    color_stack: Vec<Rc<AnsiStyle>>,
14    upstream: AnsiWriter<W>,
15}
16
17/// Writes to something implementing `std::io::Write`
18pub struct IoWrite<W> {
19    upstream: W,
20}
21
22impl<W> Debug for IoWrite<W> {
23    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
24        f.debug_struct("IoWrite").finish()
25    }
26}
27
28impl<W> IoWrite<W> {
29    /// Creates a new terminal writer.
30    pub fn new(upstream: W) -> IoWrite<W> {
31        IoWrite { upstream }
32    }
33}
34
35#[cfg(feature = "std")]
36impl<'a, W, T: Text<'a>> Render<'a, T> for IoWrite<W>
37where
38    W: std::io::Write,
39{
40    type Error = std::io::Error;
41
42    fn write_all(&mut self, s: &[T]) -> std::io::Result<()> {
43        for i in s {
44            self.upstream.write_all(i.as_str().as_bytes())?;
45        }
46
47        Ok(())
48    }
49
50    fn fail_doc(&self) -> Self::Error {
51        std::io::Error::other("Document failed to render")
52    }
53}
54
55#[cfg(feature = "std")]
56impl<'a, W, T: Text<'a>> RenderAnnotated<'a, T> for IoWrite<W>
57where
58    W: std::io::Write,
59{
60    fn push_annotation(&mut self, _: Rc<AnsiStyle>) -> Result<(), Self::Error> {
61        Ok(())
62    }
63
64    fn pop_annotation(&mut self) -> Result<(), Self::Error> {
65        Ok(())
66    }
67}
68
69impl<W> Debug for TerminalWriter<W> {
70    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
71        f.debug_struct("TerminalWriter").finish()
72    }
73}
74
75impl<W: Write> TerminalWriter<W> {
76    /// Creates a new terminal writer.
77    pub fn new(upstream: W) -> Self {
78        TerminalWriter { color_stack: Vec::new(), upstream: AnsiWriter::new(upstream) }
79    }
80    /// Creates a new terminal writer with a specific color.
81    pub fn with_color(mut self, color: AnsiAbility) -> Self {
82        self.upstream.set_ability(color);
83        self
84    }
85}
86
87impl<'a, W, T: Text<'a>> Render<'a, T> for TerminalWriter<W>
88where
89    W: Write,
90{
91    type Error = Error;
92
93    fn write_all(&mut self, s: &[T]) -> std::io::Result<()> {
94        for i in s {
95            self.upstream.write_all(i.as_str().as_bytes())?;
96        }
97
98        Ok(())
99    }
100
101    fn fail_doc(&self) -> Self::Error {
102        Error::other("Document failed to render")
103    }
104}
105
106impl<'a, W: Write, T: Text<'a>> RenderAnnotated<'a, T> for TerminalWriter<W> {
107    fn push_annotation(&mut self, color: Rc<AnsiStyle>) -> Result<(), Self::Error> {
108        self.color_stack.push(color.clone());
109        self.upstream.set_style(&color)
110    }
111
112    fn pop_annotation(&mut self) -> Result<(), Self::Error> {
113        self.color_stack.pop();
114        match self.color_stack.last() {
115            Some(previous) => self.upstream.set_style(previous),
116            None => self.upstream.reset_style(),
117        }
118    }
119}
120
121/// Writes to something implementing `std::io::Write`
122pub struct VecWrite<'v, T> {
123    upstream: &'v mut Vec<T>,
124}
125
126impl<'v, W> Debug for VecWrite<'v, W> {
127    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
128        f.debug_struct("VecWrite").finish()
129    }
130}
131
132impl<'v, T> VecWrite<'v, T> {
133    /// Creates a new terminal writer.
134    pub fn new(upstream: &'v mut Vec<T>) -> VecWrite<'v, T> {
135        VecWrite { upstream }
136    }
137}
138
139#[cfg(feature = "std")]
140impl<'a, T: Text<'a>> Render<'a, T> for VecWrite<'_, T> {
141    type Error = &'static str;
142
143    fn write_all(&mut self, s: &[T]) -> Result<(), &'static str> {
144        for i in s {
145            self.upstream.push(i.clone());
146        }
147
148        Ok(())
149    }
150
151    fn fail_doc(&self) -> Self::Error {
152        "Document failed to render"
153    }
154}
155
156#[cfg(feature = "std")]
157impl<'a, T: Text<'a>> RenderAnnotated<'a, T> for VecWrite<'_, T> {
158    fn push_annotation(&mut self, _: Rc<AnsiStyle>) -> Result<(), Self::Error> {
159        Ok(())
160    }
161
162    fn pop_annotation(&mut self) -> Result<(), Self::Error> {
163        Ok(())
164    }
165}