env_logger/fmt/writer/
mod.rs1mod buffer;
2mod target;
3
4use self::buffer::BufferWriter;
5use std::{io, mem, sync::Mutex};
6
7pub(super) use self::buffer::Buffer;
8
9pub use target::Target;
10
11#[allow(clippy::exhaustive_enums)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Default)]
14pub enum WriteStyle {
15 #[default]
17 Auto,
18 Always,
20 Never,
22}
23
24#[cfg(feature = "color")]
25impl From<anstream::ColorChoice> for WriteStyle {
26 fn from(choice: anstream::ColorChoice) -> Self {
27 match choice {
28 anstream::ColorChoice::Auto => Self::Auto,
29 anstream::ColorChoice::Always => Self::Always,
30 anstream::ColorChoice::AlwaysAnsi => Self::Always,
31 anstream::ColorChoice::Never => Self::Never,
32 }
33 }
34}
35
36#[cfg(feature = "color")]
37impl From<WriteStyle> for anstream::ColorChoice {
38 fn from(choice: WriteStyle) -> Self {
39 match choice {
40 WriteStyle::Auto => anstream::ColorChoice::Auto,
41 WriteStyle::Always => anstream::ColorChoice::Always,
42 WriteStyle::Never => anstream::ColorChoice::Never,
43 }
44 }
45}
46
47#[derive(Debug)]
49pub(crate) struct Writer {
50 inner: BufferWriter,
51}
52
53impl Writer {
54 pub(crate) fn write_style(&self) -> WriteStyle {
55 self.inner.write_style()
56 }
57
58 pub(super) fn buffer(&self) -> Buffer {
59 self.inner.buffer()
60 }
61
62 pub(super) fn print(&self, buf: &Buffer) -> io::Result<()> {
63 self.inner.print(buf)
64 }
65}
66
67#[derive(Debug)]
71pub(crate) struct Builder {
72 target: Target,
73 write_style: WriteStyle,
74 is_test: bool,
75 built: bool,
76}
77
78impl Builder {
79 pub(crate) fn new() -> Self {
81 Builder {
82 target: Default::default(),
83 write_style: Default::default(),
84 is_test: false,
85 built: false,
86 }
87 }
88
89 pub(crate) fn target(&mut self, target: Target) -> &mut Self {
91 self.target = target;
92 self
93 }
94
95 pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
101 self.write_style(parse_write_style(write_style))
102 }
103
104 pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self {
106 self.write_style = write_style;
107 self
108 }
109
110 #[allow(clippy::wrong_self_convention)]
112 pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self {
113 self.is_test = is_test;
114 self
115 }
116
117 pub(crate) fn build(&mut self) -> Writer {
119 assert!(!self.built, "attempt to re-use consumed builder");
120 self.built = true;
121
122 let color_choice = self.write_style;
123 #[cfg(feature = "auto-color")]
124 let color_choice = if color_choice == WriteStyle::Auto {
125 match &self.target {
126 Target::Stdout => anstream::AutoStream::choice(&io::stdout()).into(),
127 Target::Stderr => anstream::AutoStream::choice(&io::stderr()).into(),
128 Target::Pipe(_) => color_choice,
129 }
130 } else {
131 color_choice
132 };
133 let color_choice = if color_choice == WriteStyle::Auto {
134 WriteStyle::Never
135 } else {
136 color_choice
137 };
138
139 let writer = match mem::take(&mut self.target) {
140 Target::Stdout => BufferWriter::stdout(self.is_test, color_choice),
141 Target::Stderr => BufferWriter::stderr(self.is_test, color_choice),
142 Target::Pipe(pipe) => BufferWriter::pipe(Box::new(Mutex::new(pipe)), color_choice),
143 };
144
145 Writer { inner: writer }
146 }
147}
148
149impl Default for Builder {
150 fn default() -> Self {
151 Builder::new()
152 }
153}
154
155fn parse_write_style(spec: &str) -> WriteStyle {
156 match spec {
157 "auto" => WriteStyle::Auto,
158 "always" => WriteStyle::Always,
159 "never" => WriteStyle::Never,
160 _ => Default::default(),
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn parse_write_style_valid() {
170 let inputs = vec![
171 ("auto", WriteStyle::Auto),
172 ("always", WriteStyle::Always),
173 ("never", WriteStyle::Never),
174 ];
175
176 for (input, expected) in inputs {
177 assert_eq!(expected, parse_write_style(input));
178 }
179 }
180
181 #[test]
182 fn parse_write_style_invalid() {
183 let inputs = vec!["", "true", "false", "NEVER!!"];
184
185 for input in inputs {
186 assert_eq!(WriteStyle::Auto, parse_write_style(input));
187 }
188 }
189}