diff options
Diffstat (limited to 'vendor/env_logger/src/fmt/mod.rs')
-rw-r--r-- | vendor/env_logger/src/fmt/mod.rs | 652 |
1 files changed, 0 insertions, 652 deletions
diff --git a/vendor/env_logger/src/fmt/mod.rs b/vendor/env_logger/src/fmt/mod.rs deleted file mode 100644 index 21e09577a..000000000 --- a/vendor/env_logger/src/fmt/mod.rs +++ /dev/null @@ -1,652 +0,0 @@ -//! Formatting for log records. -//! -//! This module contains a [`Formatter`] that can be used to format log records -//! into without needing temporary allocations. Usually you won't need to worry -//! about the contents of this module and can use the `Formatter` like an ordinary -//! [`Write`]. -//! -//! # Formatting log records -//! -//! The format used to print log records can be customised using the [`Builder::format`] -//! method. -//! Custom formats can apply different color and weight to printed values using -//! [`Style`] builders. -//! -//! ``` -//! use std::io::Write; -//! -//! let mut builder = env_logger::Builder::new(); -//! -//! builder.format(|buf, record| { -//! writeln!(buf, "{}: {}", -//! record.level(), -//! record.args()) -//! }); -//! ``` -//! -//! [`Formatter`]: struct.Formatter.html -//! [`Style`]: struct.Style.html -//! [`Builder::format`]: ../struct.Builder.html#method.format -//! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html - -use std::cell::RefCell; -use std::fmt::Display; -use std::io::prelude::*; -use std::rc::Rc; -use std::{fmt, io, mem}; - -use log::Record; - -mod humantime; -pub(crate) mod writer; - -pub use self::humantime::glob::*; -pub use self::writer::glob::*; - -use self::writer::{Buffer, Writer}; - -pub(crate) mod glob { - pub use super::{Target, TimestampPrecision, WriteStyle}; -} - -/// Formatting precision of timestamps. -/// -/// Seconds give precision of full seconds, milliseconds give thousands of a -/// second (3 decimal digits), microseconds are millionth of a second (6 decimal -/// digits) and nanoseconds are billionth of a second (9 decimal digits). -#[derive(Copy, Clone, Debug)] -pub enum TimestampPrecision { - /// Full second precision (0 decimal digits) - Seconds, - /// Millisecond precision (3 decimal digits) - Millis, - /// Microsecond precision (6 decimal digits) - Micros, - /// Nanosecond precision (9 decimal digits) - Nanos, -} - -/// The default timestamp precision is seconds. -impl Default for TimestampPrecision { - fn default() -> Self { - TimestampPrecision::Seconds - } -} - -/// A formatter to write logs into. -/// -/// `Formatter` implements the standard [`Write`] trait for writing log records. -/// It also supports terminal colors, through the [`style`] method. -/// -/// # Examples -/// -/// Use the [`writeln`] macro to format a log record. -/// An instance of a `Formatter` is passed to an `env_logger` format as `buf`: -/// -/// ``` -/// use std::io::Write; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())); -/// ``` -/// -/// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html -/// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html -/// [`style`]: #method.style -pub struct Formatter { - buf: Rc<RefCell<Buffer>>, - write_style: WriteStyle, -} - -impl Formatter { - pub(crate) fn new(writer: &Writer) -> Self { - Formatter { - buf: Rc::new(RefCell::new(writer.buffer())), - write_style: writer.write_style(), - } - } - - pub(crate) fn write_style(&self) -> WriteStyle { - self.write_style - } - - pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> { - writer.print(&self.buf.borrow()) - } - - pub(crate) fn clear(&mut self) { - self.buf.borrow_mut().clear() - } -} - -impl Write for Formatter { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.buf.borrow_mut().write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - self.buf.borrow_mut().flush() - } -} - -impl fmt::Debug for Formatter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Formatter").finish() - } -} - -pub(crate) type FormatFn = Box<dyn Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>; - -pub(crate) struct Builder { - pub format_timestamp: Option<TimestampPrecision>, - pub format_module_path: bool, - pub format_target: bool, - pub format_level: bool, - pub format_indent: Option<usize>, - pub custom_format: Option<FormatFn>, - pub format_suffix: &'static str, - built: bool, -} - -impl Default for Builder { - fn default() -> Self { - Builder { - format_timestamp: Some(Default::default()), - format_module_path: false, - format_target: true, - format_level: true, - format_indent: Some(4), - custom_format: None, - format_suffix: "\n", - built: false, - } - } -} - -impl Builder { - /// Convert the format into a callable function. - /// - /// If the `custom_format` is `Some`, then any `default_format` switches are ignored. - /// If the `custom_format` is `None`, then a default format is returned. - /// Any `default_format` switches set to `false` won't be written by the format. - pub fn build(&mut self) -> FormatFn { - assert!(!self.built, "attempt to re-use consumed builder"); - - let built = mem::replace( - self, - Builder { - built: true, - ..Default::default() - }, - ); - - if let Some(fmt) = built.custom_format { - fmt - } else { - Box::new(move |buf, record| { - let fmt = DefaultFormat { - timestamp: built.format_timestamp, - module_path: built.format_module_path, - target: built.format_target, - level: built.format_level, - written_header_value: false, - indent: built.format_indent, - suffix: built.format_suffix, - buf, - }; - - fmt.write(record) - }) - } - } -} - -#[cfg(feature = "termcolor")] -type SubtleStyle = StyledValue<'static, &'static str>; -#[cfg(not(feature = "termcolor"))] -type SubtleStyle = &'static str; - -/// The default format. -/// -/// This format needs to work with any combination of crate features. -struct DefaultFormat<'a> { - timestamp: Option<TimestampPrecision>, - module_path: bool, - target: bool, - level: bool, - written_header_value: bool, - indent: Option<usize>, - buf: &'a mut Formatter, - suffix: &'a str, -} - -impl<'a> DefaultFormat<'a> { - fn write(mut self, record: &Record) -> io::Result<()> { - self.write_timestamp()?; - self.write_level(record)?; - self.write_module_path(record)?; - self.write_target(record)?; - self.finish_header()?; - - self.write_args(record) - } - - fn subtle_style(&self, text: &'static str) -> SubtleStyle { - #[cfg(feature = "termcolor")] - { - self.buf - .style() - .set_color(Color::Black) - .set_intense(true) - .clone() - .into_value(text) - } - #[cfg(not(feature = "termcolor"))] - { - text - } - } - - fn write_header_value<T>(&mut self, value: T) -> io::Result<()> - where - T: Display, - { - if !self.written_header_value { - self.written_header_value = true; - - let open_brace = self.subtle_style("["); - write!(self.buf, "{}{}", open_brace, value) - } else { - write!(self.buf, " {}", value) - } - } - - fn write_level(&mut self, record: &Record) -> io::Result<()> { - if !self.level { - return Ok(()); - } - - let level = { - #[cfg(feature = "termcolor")] - { - self.buf.default_styled_level(record.level()) - } - #[cfg(not(feature = "termcolor"))] - { - record.level() - } - }; - - self.write_header_value(format_args!("{:<5}", level)) - } - - fn write_timestamp(&mut self) -> io::Result<()> { - #[cfg(feature = "humantime")] - { - use self::TimestampPrecision::*; - let ts = match self.timestamp { - None => return Ok(()), - Some(Seconds) => self.buf.timestamp_seconds(), - Some(Millis) => self.buf.timestamp_millis(), - Some(Micros) => self.buf.timestamp_micros(), - Some(Nanos) => self.buf.timestamp_nanos(), - }; - - self.write_header_value(ts) - } - #[cfg(not(feature = "humantime"))] - { - // Trick the compiler to think we have used self.timestamp - // Workaround for "field is never used: `timestamp`" compiler nag. - let _ = self.timestamp; - Ok(()) - } - } - - fn write_module_path(&mut self, record: &Record) -> io::Result<()> { - if !self.module_path { - return Ok(()); - } - - if let Some(module_path) = record.module_path() { - self.write_header_value(module_path) - } else { - Ok(()) - } - } - - fn write_target(&mut self, record: &Record) -> io::Result<()> { - if !self.target { - return Ok(()); - } - - match record.target() { - "" => Ok(()), - target => self.write_header_value(target), - } - } - - fn finish_header(&mut self) -> io::Result<()> { - if self.written_header_value { - let close_brace = self.subtle_style("]"); - write!(self.buf, "{} ", close_brace) - } else { - Ok(()) - } - } - - fn write_args(&mut self, record: &Record) -> io::Result<()> { - match self.indent { - // Fast path for no indentation - None => write!(self.buf, "{}{}", record.args(), self.suffix), - - Some(indent_count) => { - // Create a wrapper around the buffer only if we have to actually indent the message - - struct IndentWrapper<'a, 'b: 'a> { - fmt: &'a mut DefaultFormat<'b>, - indent_count: usize, - } - - impl<'a, 'b> Write for IndentWrapper<'a, 'b> { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - let mut first = true; - for chunk in buf.split(|&x| x == b'\n') { - if !first { - write!( - self.fmt.buf, - "{}{:width$}", - self.fmt.suffix, - "", - width = self.indent_count - )?; - } - self.fmt.buf.write_all(chunk)?; - first = false; - } - - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - self.fmt.buf.flush() - } - } - - // The explicit scope here is just to make older versions of Rust happy - { - let mut wrapper = IndentWrapper { - fmt: self, - indent_count, - }; - write!(wrapper, "{}", record.args())?; - } - - write!(self.buf, "{}", self.suffix)?; - - Ok(()) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use log::{Level, Record}; - - fn write_record(record: Record, fmt: DefaultFormat) -> String { - let buf = fmt.buf.buf.clone(); - - fmt.write(&record).expect("failed to write record"); - - let buf = buf.borrow(); - String::from_utf8(buf.bytes().to_vec()).expect("failed to read record") - } - - fn write_target<'a>(target: &'a str, fmt: DefaultFormat) -> String { - write_record( - Record::builder() - .args(format_args!("log\nmessage")) - .level(Level::Info) - .file(Some("test.rs")) - .line(Some(144)) - .module_path(Some("test::path")) - .target(target) - .build(), - fmt, - ) - } - - fn write(fmt: DefaultFormat) -> String { - write_target("", fmt) - } - - #[test] - fn format_with_header() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } - - #[test] - fn format_no_header() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("log\nmessage\n", written); - } - - #[test] - fn format_indent_spaces() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: Some(4), - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\n message\n", written); - } - - #[test] - fn format_indent_zero_spaces() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: Some(0), - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } - - #[test] - fn format_indent_spaces_no_header() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: Some(4), - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("log\n message\n", written); - } - - #[test] - fn format_suffix() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: None, - suffix: "\n\n", - buf: &mut f, - }); - - assert_eq!("log\nmessage\n\n", written); - } - - #[test] - fn format_suffix_with_indent() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: Some(4), - suffix: "\n\n", - buf: &mut f, - }); - - assert_eq!("log\n\n message\n\n", written); - } - - #[test] - fn format_target() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write_target( - "target", - DefaultFormat { - timestamp: None, - module_path: true, - target: true, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }, - ); - - assert_eq!("[INFO test::path target] log\nmessage\n", written); - } - - #[test] - fn format_empty_target() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: true, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } - - #[test] - fn format_no_target() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write_target( - "target", - DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }, - ); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } -} |