summaryrefslogtreecommitdiffstats
path: root/vendor/env_logger/src/fmt/writer
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:03 +0000
commit64d98f8ee037282c35007b64c2649055c56af1db (patch)
tree5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /vendor/env_logger/src/fmt/writer
parentAdding debian version 1.67.1+dfsg1-1. (diff)
downloadrustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz
rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/env_logger/src/fmt/writer')
-rw-r--r--vendor/env_logger/src/fmt/writer/atty.rs33
-rw-r--r--vendor/env_logger/src/fmt/writer/mod.rs253
-rw-r--r--vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs532
-rw-r--r--vendor/env_logger/src/fmt/writer/termcolor/mod.rs12
-rw-r--r--vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs72
5 files changed, 902 insertions, 0 deletions
diff --git a/vendor/env_logger/src/fmt/writer/atty.rs b/vendor/env_logger/src/fmt/writer/atty.rs
new file mode 100644
index 000000000..1a133eeff
--- /dev/null
+++ b/vendor/env_logger/src/fmt/writer/atty.rs
@@ -0,0 +1,33 @@
+/*
+This internal module contains the terminal detection implementation.
+
+If the `auto-color` feature is enabled then we detect whether we're attached to a particular TTY.
+Otherwise, assume we're not attached to anything. This effectively prevents styles from being
+printed.
+*/
+
+#[cfg(feature = "auto-color")]
+mod imp {
+ use is_terminal::IsTerminal;
+
+ pub(in crate::fmt) fn is_stdout() -> bool {
+ std::io::stdout().is_terminal()
+ }
+
+ pub(in crate::fmt) fn is_stderr() -> bool {
+ std::io::stderr().is_terminal()
+ }
+}
+
+#[cfg(not(feature = "auto-color"))]
+mod imp {
+ pub(in crate::fmt) fn is_stdout() -> bool {
+ false
+ }
+
+ pub(in crate::fmt) fn is_stderr() -> bool {
+ false
+ }
+}
+
+pub(in crate::fmt) use self::imp::*;
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..7f4b6f949
--- /dev/null
+++ b/vendor/env_logger/src/fmt/writer/mod.rs
@@ -0,0 +1,253 @@
+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`.
+ #[allow(clippy::wrong_self_convention)]
+ 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(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));
+ }
+ }
+}
diff --git a/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs b/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs
new file mode 100644
index 000000000..89c382239
--- /dev/null
+++ b/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs
@@ -0,0 +1,532 @@
+use std::borrow::Cow;
+use std::cell::RefCell;
+use std::fmt;
+use std::io::{self, Write};
+use std::rc::Rc;
+use std::sync::Mutex;
+
+use log::Level;
+use termcolor::{self, ColorChoice, ColorSpec, WriteColor};
+
+use crate::fmt::{Formatter, WritableTarget, WriteStyle};
+
+pub(in crate::fmt::writer) mod glob {
+ pub use super::*;
+}
+
+impl Formatter {
+ /// Begin a new [`Style`].
+ ///
+ /// # Examples
+ ///
+ /// Create a bold, red colored style and use it to print the log level:
+ ///
+ /// ```
+ /// use std::io::Write;
+ /// use env_logger::fmt::Color;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut level_style = buf.style();
+ ///
+ /// level_style.set_color(Color::Red).set_bold(true);
+ ///
+ /// writeln!(buf, "{}: {}",
+ /// level_style.value(record.level()),
+ /// record.args())
+ /// });
+ /// ```
+ ///
+ /// [`Style`]: struct.Style.html
+ pub fn style(&self) -> Style {
+ Style {
+ buf: self.buf.clone(),
+ spec: ColorSpec::new(),
+ }
+ }
+
+ /// Get the default [`Style`] for the given level.
+ ///
+ /// The style can be used to print other values besides the level.
+ pub fn default_level_style(&self, level: Level) -> Style {
+ let mut level_style = self.style();
+ match level {
+ Level::Trace => level_style.set_color(Color::Cyan),
+ Level::Debug => level_style.set_color(Color::Blue),
+ Level::Info => level_style.set_color(Color::Green),
+ Level::Warn => level_style.set_color(Color::Yellow),
+ Level::Error => level_style.set_color(Color::Red).set_bold(true),
+ };
+ level_style
+ }
+
+ /// Get a printable [`Style`] for the given level.
+ ///
+ /// The style can only be used to print the level.
+ pub fn default_styled_level(&self, level: Level) -> StyledValue<'static, Level> {
+ self.default_level_style(level).into_value(level)
+ }
+}
+
+pub(in crate::fmt::writer) struct BufferWriter {
+ inner: termcolor::BufferWriter,
+ uncolored_target: Option<WritableTarget>,
+}
+
+pub(in crate::fmt) struct Buffer {
+ inner: termcolor::Buffer,
+ has_uncolored_target: bool,
+}
+
+impl BufferWriter {
+ pub(in crate::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self {
+ BufferWriter {
+ inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
+ uncolored_target: if is_test {
+ Some(WritableTarget::Stderr)
+ } else {
+ None
+ },
+ }
+ }
+
+ pub(in crate::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self {
+ BufferWriter {
+ inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()),
+ uncolored_target: if is_test {
+ Some(WritableTarget::Stdout)
+ } else {
+ None
+ },
+ }
+ }
+
+ pub(in crate::fmt::writer) fn pipe(
+ write_style: WriteStyle,
+ pipe: Box<Mutex<dyn io::Write + Send + 'static>>,
+ ) -> Self {
+ BufferWriter {
+ // The inner Buffer is never printed from, but it is still needed to handle coloring and other formatting
+ inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
+ uncolored_target: Some(WritableTarget::Pipe(pipe)),
+ }
+ }
+
+ pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
+ Buffer {
+ inner: self.inner.buffer(),
+ has_uncolored_target: self.uncolored_target.is_some(),
+ }
+ }
+
+ pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
+ if let Some(target) = &self.uncolored_target {
+ // This impl uses the `eprint` and `print` macros
+ // instead of `termcolor`'s buffer.
+ // This is so their output can be captured by `cargo test`
+ let log = String::from_utf8_lossy(buf.bytes());
+
+ match target {
+ WritableTarget::Stderr => eprint!("{}", log),
+ WritableTarget::Stdout => print!("{}", log),
+ WritableTarget::Pipe(pipe) => write!(pipe.lock().unwrap(), "{}", log)?,
+ }
+
+ Ok(())
+ } else {
+ self.inner.print(&buf.inner)
+ }
+ }
+}
+
+impl Buffer {
+ pub(in crate::fmt) fn clear(&mut self) {
+ self.inner.clear()
+ }
+
+ pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ self.inner.write(buf)
+ }
+
+ pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> {
+ self.inner.flush()
+ }
+
+ pub(in crate::fmt) fn bytes(&self) -> &[u8] {
+ self.inner.as_slice()
+ }
+
+ fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
+ // Ignore styles for test captured logs because they can't be printed
+ if !self.has_uncolored_target {
+ self.inner.set_color(spec)
+ } else {
+ Ok(())
+ }
+ }
+
+ fn reset(&mut self) -> io::Result<()> {
+ // Ignore styles for test captured logs because they can't be printed
+ if !self.has_uncolored_target {
+ self.inner.reset()
+ } else {
+ Ok(())
+ }
+ }
+}
+
+impl WriteStyle {
+ fn into_color_choice(self) -> ColorChoice {
+ match self {
+ WriteStyle::Always => ColorChoice::Always,
+ WriteStyle::Auto => ColorChoice::Auto,
+ WriteStyle::Never => ColorChoice::Never,
+ }
+ }
+}
+
+/// A set of styles to apply to the terminal output.
+///
+/// Call [`Formatter::style`] to get a `Style` and use the builder methods to
+/// set styling properties, like [color] and [weight].
+/// To print a value using the style, wrap it in a call to [`value`] when the log
+/// record is formatted.
+///
+/// # Examples
+///
+/// Create a bold, red colored style and use it to print the log level:
+///
+/// ```
+/// use std::io::Write;
+/// use env_logger::fmt::Color;
+///
+/// let mut builder = env_logger::Builder::new();
+///
+/// builder.format(|buf, record| {
+/// let mut level_style = buf.style();
+///
+/// level_style.set_color(Color::Red).set_bold(true);
+///
+/// writeln!(buf, "{}: {}",
+/// level_style.value(record.level()),
+/// record.args())
+/// });
+/// ```
+///
+/// Styles can be re-used to output multiple values:
+///
+/// ```
+/// use std::io::Write;
+/// use env_logger::fmt::Color;
+///
+/// let mut builder = env_logger::Builder::new();
+///
+/// builder.format(|buf, record| {
+/// let mut bold = buf.style();
+///
+/// bold.set_bold(true);
+///
+/// writeln!(buf, "{}: {} {}",
+/// bold.value(record.level()),
+/// bold.value("some bold text"),
+/// record.args())
+/// });
+/// ```
+///
+/// [`Formatter::style`]: struct.Formatter.html#method.style
+/// [color]: #method.set_color
+/// [weight]: #method.set_bold
+/// [`value`]: #method.value
+#[derive(Clone)]
+pub struct Style {
+ buf: Rc<RefCell<Buffer>>,
+ spec: ColorSpec,
+}
+
+/// A value that can be printed using the given styles.
+///
+/// It is the result of calling [`Style::value`].
+///
+/// [`Style::value`]: struct.Style.html#method.value
+pub struct StyledValue<'a, T> {
+ style: Cow<'a, Style>,
+ value: T,
+}
+
+impl Style {
+ /// Set the text color.
+ ///
+ /// # Examples
+ ///
+ /// Create a style with red text:
+ ///
+ /// ```
+ /// use std::io::Write;
+ /// use env_logger::fmt::Color;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut style = buf.style();
+ ///
+ /// style.set_color(Color::Red);
+ ///
+ /// writeln!(buf, "{}", style.value(record.args()))
+ /// });
+ /// ```
+ pub fn set_color(&mut self, color: Color) -> &mut Style {
+ self.spec.set_fg(Some(color.into_termcolor()));
+ self
+ }
+
+ /// Set the text weight.
+ ///
+ /// If `yes` is true then text will be written in bold.
+ /// If `yes` is false then text will be written in the default weight.
+ ///
+ /// # Examples
+ ///
+ /// Create a style with bold text:
+ ///
+ /// ```
+ /// use std::io::Write;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut style = buf.style();
+ ///
+ /// style.set_bold(true);
+ ///
+ /// writeln!(buf, "{}", style.value(record.args()))
+ /// });
+ /// ```
+ pub fn set_bold(&mut self, yes: bool) -> &mut Style {
+ self.spec.set_bold(yes);
+ self
+ }
+
+ /// Set the text intensity.
+ ///
+ /// If `yes` is true then text will be written in a brighter color.
+ /// If `yes` is false then text will be written in the default color.
+ ///
+ /// # Examples
+ ///
+ /// Create a style with intense text:
+ ///
+ /// ```
+ /// use std::io::Write;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut style = buf.style();
+ ///
+ /// style.set_intense(true);
+ ///
+ /// writeln!(buf, "{}", style.value(record.args()))
+ /// });
+ /// ```
+ pub fn set_intense(&mut self, yes: bool) -> &mut Style {
+ self.spec.set_intense(yes);
+ self
+ }
+
+ /// Set whether the text is dimmed.
+ ///
+ /// If `yes` is true then text will be written in a dimmer color.
+ /// If `yes` is false then text will be written in the default color.
+ ///
+ /// # Examples
+ ///
+ /// Create a style with dimmed text:
+ ///
+ /// ```
+ /// use std::io::Write;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut style = buf.style();
+ ///
+ /// style.set_dimmed(true);
+ ///
+ /// writeln!(buf, "{}", style.value(record.args()))
+ /// });
+ /// ```
+ pub fn set_dimmed(&mut self, yes: bool) -> &mut Style {
+ self.spec.set_dimmed(yes);
+ self
+ }
+
+ /// Set the background color.
+ ///
+ /// # Examples
+ ///
+ /// Create a style with a yellow background:
+ ///
+ /// ```
+ /// use std::io::Write;
+ /// use env_logger::fmt::Color;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut style = buf.style();
+ ///
+ /// style.set_bg(Color::Yellow);
+ ///
+ /// writeln!(buf, "{}", style.value(record.args()))
+ /// });
+ /// ```
+ pub fn set_bg(&mut self, color: Color) -> &mut Style {
+ self.spec.set_bg(Some(color.into_termcolor()));
+ self
+ }
+
+ /// Wrap a value in the style.
+ ///
+ /// The same `Style` can be used to print multiple different values.
+ ///
+ /// # Examples
+ ///
+ /// Create a bold, red colored style and use it to print the log level:
+ ///
+ /// ```
+ /// use std::io::Write;
+ /// use env_logger::fmt::Color;
+ ///
+ /// let mut builder = env_logger::Builder::new();
+ ///
+ /// builder.format(|buf, record| {
+ /// let mut style = buf.style();
+ ///
+ /// style.set_color(Color::Red).set_bold(true);
+ ///
+ /// writeln!(buf, "{}: {}",
+ /// style.value(record.level()),
+ /// record.args())
+ /// });
+ /// ```
+ pub fn value<T>(&self, value: T) -> StyledValue<T> {
+ StyledValue {
+ style: Cow::Borrowed(self),
+ value,
+ }
+ }
+
+ /// Wrap a value in the style by taking ownership of it.
+ pub(crate) fn into_value<T>(self, value: T) -> StyledValue<'static, T> {
+ StyledValue {
+ style: Cow::Owned(self),
+ value,
+ }
+ }
+}
+
+impl<'a, T> StyledValue<'a, T> {
+ fn write_fmt<F>(&self, f: F) -> fmt::Result
+ where
+ F: FnOnce() -> fmt::Result,
+ {
+ self.style
+ .buf
+ .borrow_mut()
+ .set_color(&self.style.spec)
+ .map_err(|_| fmt::Error)?;
+
+ // Always try to reset the terminal style, even if writing failed
+ let write = f();
+ let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error);
+
+ write.and(reset)
+ }
+}
+
+impl fmt::Debug for Style {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Style").field("spec", &self.spec).finish()
+ }
+}
+
+macro_rules! impl_styled_value_fmt {
+ ($($fmt_trait:path),*) => {
+ $(
+ impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> {
+ fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
+ self.write_fmt(|| T::fmt(&self.value, f))
+ }
+ }
+ )*
+ };
+}
+
+impl_styled_value_fmt!(
+ fmt::Debug,
+ fmt::Display,
+ fmt::Pointer,
+ fmt::Octal,
+ fmt::Binary,
+ fmt::UpperHex,
+ fmt::LowerHex,
+ fmt::UpperExp,
+ fmt::LowerExp
+);
+
+// The `Color` type is copied from https://github.com/BurntSushi/termcolor
+
+/// The set of available colors for the terminal foreground/background.
+///
+/// The `Ansi256` and `Rgb` colors will only output the correct codes when
+/// paired with the `Ansi` `WriteColor` implementation.
+///
+/// The `Ansi256` and `Rgb` color types are not supported when writing colors
+/// on Windows using the console. If they are used on Windows, then they are
+/// silently ignored and no colors will be emitted.
+///
+/// This set may expand over time.
+///
+/// This type has a `FromStr` impl that can parse colors from their human
+/// readable form. The format is as follows:
+///
+/// 1. Any of the explicitly listed colors in English. They are matched
+/// case insensitively.
+/// 2. A single 8-bit integer, in either decimal or hexadecimal format.
+/// 3. A triple of 8-bit integers separated by a comma, where each integer is
+/// in decimal or hexadecimal format.
+///
+/// Hexadecimal numbers are written with a `0x` prefix.
+#[allow(missing_docs)]
+#[non_exhaustive]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum Color {
+ Black,
+ Blue,
+ Green,
+ Red,
+ Cyan,
+ Magenta,
+ Yellow,
+ White,
+ Ansi256(u8),
+ Rgb(u8, u8, u8),
+}
+
+impl Color {
+ fn into_termcolor(self) -> termcolor::Color {
+ match self {
+ Color::Black => termcolor::Color::Black,
+ Color::Blue => termcolor::Color::Blue,
+ Color::Green => termcolor::Color::Green,
+ Color::Red => termcolor::Color::Red,
+ Color::Cyan => termcolor::Color::Cyan,
+ Color::Magenta => termcolor::Color::Magenta,
+ Color::Yellow => termcolor::Color::Yellow,
+ Color::White => termcolor::Color::White,
+ Color::Ansi256(value) => termcolor::Color::Ansi256(value),
+ Color::Rgb(r, g, b) => termcolor::Color::Rgb(r, g, b),
+ }
+ }
+}
diff --git a/vendor/env_logger/src/fmt/writer/termcolor/mod.rs b/vendor/env_logger/src/fmt/writer/termcolor/mod.rs
new file mode 100644
index 000000000..20f01979e
--- /dev/null
+++ b/vendor/env_logger/src/fmt/writer/termcolor/mod.rs
@@ -0,0 +1,12 @@
+/*
+This internal module contains the style and terminal writing implementation.
+
+Its public API is available when the `termcolor` crate is available.
+The terminal printing is shimmed when the `termcolor` crate is not available.
+*/
+
+#[cfg_attr(feature = "color", path = "extern_impl.rs")]
+#[cfg_attr(not(feature = "color"), path = "shim_impl.rs")]
+mod imp;
+
+pub(in crate::fmt) use self::imp::*;
diff --git a/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs b/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs
new file mode 100644
index 000000000..0705770c9
--- /dev/null
+++ b/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs
@@ -0,0 +1,72 @@
+use std::{io, sync::Mutex};
+
+use crate::fmt::{WritableTarget, WriteStyle};
+
+pub(in crate::fmt::writer) mod glob {}
+
+pub(in crate::fmt::writer) struct BufferWriter {
+ target: WritableTarget,
+}
+
+pub(in crate::fmt) struct Buffer(Vec<u8>);
+
+impl BufferWriter {
+ pub(in crate::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self {
+ BufferWriter {
+ target: WritableTarget::Stderr,
+ }
+ }
+
+ pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self {
+ BufferWriter {
+ target: WritableTarget::Stdout,
+ }
+ }
+
+ pub(in crate::fmt::writer) fn pipe(
+ _write_style: WriteStyle,
+ pipe: Box<Mutex<dyn io::Write + Send + 'static>>,
+ ) -> Self {
+ BufferWriter {
+ target: WritableTarget::Pipe(pipe),
+ }
+ }
+
+ pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
+ Buffer(Vec::new())
+ }
+
+ pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
+ // This impl uses the `eprint` and `print` macros
+ // instead of using the streams directly.
+ // This is so their output can be captured by `cargo test`.
+ match &self.target {
+ // Safety: If the target type is `Pipe`, `target_pipe` will always be non-empty.
+ WritableTarget::Pipe(pipe) => pipe.lock().unwrap().write_all(&buf.0)?,
+ WritableTarget::Stdout => print!("{}", String::from_utf8_lossy(&buf.0)),
+ WritableTarget::Stderr => eprint!("{}", String::from_utf8_lossy(&buf.0)),
+ }
+
+ Ok(())
+ }
+}
+
+impl Buffer {
+ pub(in crate::fmt) fn clear(&mut self) {
+ self.0.clear();
+ }
+
+ pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ self.0.extend(buf);
+ Ok(buf.len())
+ }
+
+ pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+
+ #[cfg(test)]
+ pub(in crate::fmt) fn bytes(&self) -> &[u8] {
+ &self.0
+ }
+}