summaryrefslogtreecommitdiffstats
path: root/vendor/env_logger/src/fmt/writer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/env_logger/src/fmt/writer/mod.rs')
-rw-r--r--vendor/env_logger/src/fmt/writer/mod.rs252
1 files changed, 252 insertions, 0 deletions
diff --git a/vendor/env_logger/src/fmt/writer/mod.rs b/vendor/env_logger/src/fmt/writer/mod.rs
new file mode 100644
index 000000000..5bb535392
--- /dev/null
+++ b/vendor/env_logger/src/fmt/writer/mod.rs
@@ -0,0 +1,252 @@
+mod atty;
+mod termcolor;
+
+use self::atty::{is_stderr, is_stdout};
+use self::termcolor::BufferWriter;
+use std::{fmt, io, mem, sync::Mutex};
+
+pub(super) mod glob {
+ pub use super::termcolor::glob::*;
+ pub use super::*;
+}
+
+pub(super) use self::termcolor::Buffer;
+
+/// Log target, either `stdout`, `stderr` or a custom pipe.
+#[non_exhaustive]
+pub enum Target {
+ /// Logs will be sent to standard output.
+ Stdout,
+ /// Logs will be sent to standard error.
+ Stderr,
+ /// Logs will be sent to a custom pipe.
+ Pipe(Box<dyn io::Write + Send + 'static>),
+}
+
+impl Default for Target {
+ fn default() -> Self {
+ Target::Stderr
+ }
+}
+
+impl fmt::Debug for Target {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::Stdout => "stdout",
+ Self::Stderr => "stderr",
+ Self::Pipe(_) => "pipe",
+ }
+ )
+ }
+}
+
+/// Log target, either `stdout`, `stderr` or a custom pipe.
+///
+/// Same as `Target`, except the pipe is wrapped in a mutex for interior mutability.
+pub(super) enum WritableTarget {
+ /// Logs will be sent to standard output.
+ Stdout,
+ /// Logs will be sent to standard error.
+ Stderr,
+ /// Logs will be sent to a custom pipe.
+ Pipe(Box<Mutex<dyn io::Write + Send + 'static>>),
+}
+
+impl From<Target> for WritableTarget {
+ fn from(target: Target) -> Self {
+ match target {
+ Target::Stdout => Self::Stdout,
+ Target::Stderr => Self::Stderr,
+ Target::Pipe(pipe) => Self::Pipe(Box::new(Mutex::new(pipe))),
+ }
+ }
+}
+
+impl Default for WritableTarget {
+ fn default() -> Self {
+ Self::from(Target::default())
+ }
+}
+
+impl fmt::Debug for WritableTarget {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::Stdout => "stdout",
+ Self::Stderr => "stderr",
+ Self::Pipe(_) => "pipe",
+ }
+ )
+ }
+}
+/// Whether or not to print styles to the target.
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub enum WriteStyle {
+ /// Try to print styles, but don't force the issue.
+ Auto,
+ /// Try very hard to print styles.
+ Always,
+ /// Never print styles.
+ Never,
+}
+
+impl Default for WriteStyle {
+ fn default() -> Self {
+ WriteStyle::Auto
+ }
+}
+
+/// A terminal target with color awareness.
+pub(crate) struct Writer {
+ inner: BufferWriter,
+ write_style: WriteStyle,
+}
+
+impl Writer {
+ pub fn write_style(&self) -> WriteStyle {
+ self.write_style
+ }
+
+ pub(super) fn buffer(&self) -> Buffer {
+ self.inner.buffer()
+ }
+
+ pub(super) fn print(&self, buf: &Buffer) -> io::Result<()> {
+ self.inner.print(buf)
+ }
+}
+
+/// A builder for a terminal writer.
+///
+/// The target and style choice can be configured before building.
+#[derive(Debug)]
+pub(crate) struct Builder {
+ target: WritableTarget,
+ write_style: WriteStyle,
+ is_test: bool,
+ built: bool,
+}
+
+impl Builder {
+ /// Initialize the writer builder with defaults.
+ pub(crate) fn new() -> Self {
+ Builder {
+ target: Default::default(),
+ write_style: Default::default(),
+ is_test: false,
+ built: false,
+ }
+ }
+
+ /// Set the target to write to.
+ pub(crate) fn target(&mut self, target: Target) -> &mut Self {
+ self.target = target.into();
+ self
+ }
+
+ /// Parses a style choice string.
+ ///
+ /// See the [Disabling colors] section for more details.
+ ///
+ /// [Disabling colors]: ../index.html#disabling-colors
+ pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
+ self.write_style(parse_write_style(write_style))
+ }
+
+ /// Whether or not to print style characters when writing.
+ pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self {
+ self.write_style = write_style;
+ self
+ }
+
+ /// Whether or not to capture logs for `cargo test`.
+ pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self {
+ self.is_test = is_test;
+ self
+ }
+
+ /// Build a terminal writer.
+ pub(crate) fn build(&mut self) -> Writer {
+ assert!(!self.built, "attempt to re-use consumed builder");
+ self.built = true;
+
+ let color_choice = match self.write_style {
+ WriteStyle::Auto => {
+ if match &self.target {
+ WritableTarget::Stderr => is_stderr(),
+ WritableTarget::Stdout => is_stdout(),
+ WritableTarget::Pipe(_) => false,
+ } {
+ WriteStyle::Auto
+ } else {
+ WriteStyle::Never
+ }
+ }
+ color_choice => color_choice,
+ };
+
+ let writer = match mem::take(&mut self.target) {
+ WritableTarget::Stderr => BufferWriter::stderr(self.is_test, color_choice),
+ WritableTarget::Stdout => BufferWriter::stdout(self.is_test, color_choice),
+ WritableTarget::Pipe(pipe) => BufferWriter::pipe(self.is_test, color_choice, pipe),
+ };
+
+ Writer {
+ inner: writer,
+ write_style: self.write_style,
+ }
+ }
+}
+
+impl Default for Builder {
+ fn default() -> Self {
+ Builder::new()
+ }
+}
+
+impl fmt::Debug for Writer {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Writer").finish()
+ }
+}
+
+fn parse_write_style(spec: &str) -> WriteStyle {
+ match spec {
+ "auto" => WriteStyle::Auto,
+ "always" => WriteStyle::Always,
+ "never" => WriteStyle::Never,
+ _ => Default::default(),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn parse_write_style_valid() {
+ let inputs = vec![
+ ("auto", WriteStyle::Auto),
+ ("always", WriteStyle::Always),
+ ("never", WriteStyle::Never),
+ ];
+
+ for (input, expected) in inputs {
+ assert_eq!(expected, parse_write_style(input));
+ }
+ }
+
+ #[test]
+ fn parse_write_style_invalid() {
+ let inputs = vec!["", "true", "false", "NEVER!!"];
+
+ for input in inputs {
+ assert_eq!(WriteStyle::Auto, parse_write_style(input));
+ }
+ }
+}