logparse_pretty_print/render/
write_io.rs1#[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
11pub struct TerminalWriter<W> {
13 color_stack: Vec<Rc<AnsiStyle>>,
14 upstream: AnsiWriter<W>,
15}
16
17pub 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 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 pub fn new(upstream: W) -> Self {
78 TerminalWriter { color_stack: Vec::new(), upstream: AnsiWriter::new(upstream) }
79 }
80 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
121pub 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 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}