From 93899ba4e16fe61fb9683513ea7f3294f249fc98 Mon Sep 17 00:00:00 2001 From: Asuna Date: Fri, 16 Aug 2024 23:08:49 +0800 Subject: [PATCH] [WIP] Replace `FmtExtraInfo` with `FormatterContext` --- spdlog/src/formatter/full_formatter.rs | 27 +++++--- spdlog/src/formatter/journald_formatter.rs | 20 +++--- spdlog/src/formatter/json_formatter.rs | 31 ++++++---- spdlog/src/formatter/mod.rs | 61 ++++++------------- spdlog/src/formatter/pattern_formatter/mod.rs | 48 +++++++-------- .../pattern_formatter/pattern/full.rs | 15 ++--- .../pattern_formatter/pattern/style_range.rs | 3 +- spdlog/src/sink/file_sink.rs | 4 +- spdlog/src/sink/journald_sink.rs | 5 +- spdlog/src/sink/rotating_file_sink.rs | 4 +- spdlog/src/sink/std_stream_sink.rs | 9 +-- spdlog/src/sink/win_debug_sink.rs | 4 +- spdlog/src/sink/write_sink.rs | 4 +- spdlog/tests/pattern.rs | 11 ++-- 14 files changed, 127 insertions(+), 119 deletions(-) diff --git a/spdlog/src/formatter/full_formatter.rs b/spdlog/src/formatter/full_formatter.rs index 8f3d43a..17693aa 100644 --- a/spdlog/src/formatter/full_formatter.rs +++ b/spdlog/src/formatter/full_formatter.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Write}; use cfg_if::cfg_if; use crate::{ - formatter::{FmtExtraInfo, Formatter, LOCAL_TIME_CACHER}, + formatter::{Formatter, FormatterContext, LOCAL_TIME_CACHER}, Error, Record, StringBuf, __EOL, }; @@ -54,7 +54,8 @@ impl FullFormatter { &self, record: &Record, dest: &mut StringBuf, - ) -> Result { + ctx: &mut FormatterContext, + ) -> Result<(), fmt::Error> { cfg_if! { if #[cfg(not(feature = "flexible-string"))] { dest.reserve(crate::string_buf::RESERVE_SIZE); @@ -98,15 +99,20 @@ impl FullFormatter { dest.write_str(__EOL)?; } - Ok(FmtExtraInfo { - style_range: Some(style_range_begin..style_range_end), - }) + ctx.set_style_range(Some(style_range_begin..style_range_end)); + Ok(()) } } impl Formatter for FullFormatter { - fn format(&self, record: &Record, dest: &mut StringBuf) -> crate::Result { - self.format_impl(record, dest).map_err(Error::FormatRecord) + fn format( + &self, + record: &Record, + dest: &mut StringBuf, + ctx: &mut FormatterContext, + ) -> crate::Result<()> { + self.format_impl(record, dest, ctx) + .map_err(Error::FormatRecord) } } @@ -127,7 +133,10 @@ mod tests { fn format() { let record = Record::new(Level::Warn, "test log content"); let mut buf = StringBuf::new(); - let extra_info = FullFormatter::new().format(&record, &mut buf).unwrap(); + let mut ctx = FormatterContext::new(); + FullFormatter::new() + .format(&record, &mut buf, &mut ctx) + .unwrap(); let local_time: DateTime = record.time().into(); assert_eq!( @@ -138,6 +147,6 @@ mod tests { ), buf ); - assert_eq!(Some(27..31), extra_info.style_range()); + assert_eq!(Some(27..31), ctx.style_range()); } } diff --git a/spdlog/src/formatter/journald_formatter.rs b/spdlog/src/formatter/journald_formatter.rs index 999ca0e..14ba53a 100644 --- a/spdlog/src/formatter/journald_formatter.rs +++ b/spdlog/src/formatter/journald_formatter.rs @@ -8,7 +8,7 @@ use std::fmt::{self, Write}; use cfg_if::cfg_if; use crate::{ - formatter::{FmtExtraInfo, Formatter}, + formatter::{Formatter, FormatterContext}, Error, Record, StringBuf, __EOL, }; @@ -25,7 +25,8 @@ impl JournaldFormatter { &self, record: &Record, dest: &mut StringBuf, - ) -> Result { + ctx: &mut FormatterContext, + ) -> Result<(), fmt::Error> { cfg_if! { if #[cfg(not(feature = "flexible-string"))] { dest.reserve(crate::string_buf::RESERVE_SIZE); @@ -49,15 +50,20 @@ impl JournaldFormatter { dest.write_str(record.payload())?; dest.write_str(__EOL)?; - Ok(FmtExtraInfo { - style_range: Some(style_range_begin..style_range_end), - }) + ctx.set_style_range(Some(style_range_begin..style_range_end)); + Ok(()) } } impl Formatter for JournaldFormatter { - fn format(&self, record: &Record, dest: &mut StringBuf) -> crate::Result { - self.format_impl(record, dest).map_err(Error::FormatRecord) + fn format( + &self, + record: &Record, + dest: &mut StringBuf, + ctx: &mut FormatterContext, + ) -> crate::Result<()> { + self.format_impl(record, dest, ctx) + .map_err(Error::FormatRecord) } } diff --git a/spdlog/src/formatter/json_formatter.rs b/spdlog/src/formatter/json_formatter.rs index fdfa1cf..3b72b0f 100644 --- a/spdlog/src/formatter/json_formatter.rs +++ b/spdlog/src/formatter/json_formatter.rs @@ -8,7 +8,7 @@ use cfg_if::cfg_if; use serde::{ser::SerializeStruct, Serialize}; use crate::{ - formatter::{FmtExtraInfo, Formatter}, + formatter::{Formatter, FormatterContext}, Error, Record, StringBuf, __EOL, }; @@ -146,7 +146,8 @@ impl JsonFormatter { &self, record: &Record, dest: &mut StringBuf, - ) -> Result { + _ctx: &mut FormatterContext, + ) -> Result<(), JsonFormatterError> { cfg_if! { if #[cfg(not(feature = "flexible-string"))] { dest.reserve(crate::string_buf::RESERVE_SIZE); @@ -163,13 +164,18 @@ impl JsonFormatter { dest.write_str(__EOL)?; - Ok(FmtExtraInfo { style_range: None }) + Ok(()) } } impl Formatter for JsonFormatter { - fn format(&self, record: &Record, dest: &mut StringBuf) -> crate::Result { - self.format_impl(record, dest).map_err(Into::into) + fn format( + &self, + record: &Record, + dest: &mut StringBuf, + ctx: &mut FormatterContext, + ) -> crate::Result<()> { + self.format_impl(record, dest, ctx).map_err(Into::into) } } @@ -191,11 +197,12 @@ mod tests { let mut dest = StringBuf::new(); let formatter = JsonFormatter::new(); let record = Record::builder(Level::Info, "payload").build(); - let extra_info = formatter.format(&record, &mut dest).unwrap(); + let mut ctx = FormatterContext::new(); + formatter.format(&record, &mut dest, &mut ctx).unwrap(); let local_time: DateTime = record.time().into(); - assert_eq!(extra_info.style_range, None); + assert_eq!(ctx.style_range(), None); assert_eq!( dest.to_string(), format!( @@ -215,11 +222,12 @@ mod tests { let record = Record::builder(Level::Info, "payload") .logger_name("my-component") .build(); - let extra_info = formatter.format(&record, &mut dest).unwrap(); + let mut ctx = FormatterContext::new(); + formatter.format(&record, &mut dest, &mut ctx).unwrap(); let local_time: DateTime = record.time().into(); - assert_eq!(extra_info.style_range, None); + assert_eq!(ctx.style_range(), None); assert_eq!( dest.to_string(), format!( @@ -239,11 +247,12 @@ mod tests { let record = Record::builder(Level::Info, "payload") .source_location(Some(SourceLocation::__new("module", "file.rs", 1, 2))) .build(); - let extra_info = formatter.format(&record, &mut dest).unwrap(); + let mut ctx = FormatterContext::new(); + formatter.format(&record, &mut dest, &mut ctx).unwrap(); let local_time: DateTime = record.time().into(); - assert_eq!(extra_info.style_range, None); + assert_eq!(ctx.style_range(), None); assert_eq!( dest.to_string(), format!( diff --git a/spdlog/src/formatter/mod.rs b/spdlog/src/formatter/mod.rs index c5884c6..5efad96 100644 --- a/spdlog/src/formatter/mod.rs +++ b/spdlog/src/formatter/mod.rs @@ -84,27 +84,32 @@ use crate::{Record, Result, StringBuf}; /// [./examples]: https://github.com/SpriteOvO/spdlog-rs/tree/main/spdlog/examples pub trait Formatter: Send + Sync + DynClone { /// Formats a log record. - fn format(&self, record: &Record, dest: &mut StringBuf) -> Result; + fn format( + &self, + record: &Record, + dest: &mut StringBuf, + ctx: &mut FormatterContext, + ) -> Result<()>; } clone_trait_object!(Formatter); -/// Extra information for formatted text. -#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] -pub struct FmtExtraInfo { +#[derive(Debug, Default)] +pub struct FormatterContext { style_range: Option>, } -impl FmtExtraInfo { - /// Constructs a `FmtExtraInfo`. +impl FormatterContext { + /// Constructs a `FormatterContext`. #[must_use] - pub fn new() -> FmtExtraInfo { - FmtExtraInfo::default() + pub fn new() -> Self { + Self { style_range: None } } - /// Gets a [`FmtExtraInfoBuilder`]. - #[must_use] - pub fn builder() -> FmtExtraInfoBuilder { - FmtExtraInfoBuilder::new() + /// Sets style range (in bytes) of the formatted text. + /// + /// Users must ensure that indexes are correctly UTF-8 boundary. + pub fn set_style_range(&mut self, range: Option>) { + self.style_range = range; } /// A style range (in bytes) of the formatted text. @@ -120,35 +125,3 @@ impl FmtExtraInfo { self.style_range.clone() // This clone is cheap } } - -#[allow(missing_docs)] -#[derive(Clone, Eq, PartialEq, Hash, Debug, Default)] -pub struct FmtExtraInfoBuilder { - info: FmtExtraInfo, -} - -impl FmtExtraInfoBuilder { - /// Constructs a `FmtExtraInfoBuilder`. - /// - /// The default value of [`FmtExtraInfo`] is the same as - /// [`FmtExtraInfo::new`]. - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Sets style range (in bytes) of the formatted text. - /// - /// Users must ensure that indexes are correctly UTF-8 boundary. - #[must_use] - pub fn style_range(mut self, range: Range) -> Self { - self.info.style_range = Some(range); - self - } - - /// Builds a [`FmtExtraInfo`]. - #[must_use] - pub fn build(self) -> FmtExtraInfo { - self.info - } -} diff --git a/spdlog/src/formatter/pattern_formatter/mod.rs b/spdlog/src/formatter/pattern_formatter/mod.rs index d9bbbda..9d1a17e 100644 --- a/spdlog/src/formatter/pattern_formatter/mod.rs +++ b/spdlog/src/formatter/pattern_formatter/mod.rs @@ -5,14 +5,14 @@ pub mod __pattern; #[cfg(feature = "runtime-pattern")] mod runtime; -use std::{fmt::Write, ops::Range, sync::Arc}; +use std::{fmt::Write, sync::Arc}; use dyn_clone::*; #[cfg(feature = "runtime-pattern")] pub use runtime::*; use crate::{ - formatter::{FmtExtraInfo, FmtExtraInfoBuilder, Formatter}, + formatter::{Formatter, FormatterContext}, Error, Record, StringBuf, }; @@ -369,36 +369,31 @@ impl

Formatter for PatternFormatter

where P: 'static + Clone + Pattern, { - fn format(&self, record: &Record, dest: &mut StringBuf) -> crate::Result { - let mut ctx = PatternContext::new(FmtExtraInfoBuilder::default()); + fn format( + &self, + record: &Record, + dest: &mut StringBuf, + ctx: &mut FormatterContext, + ) -> crate::Result<()> { + let mut ctx = PatternContext::new(ctx); self.pattern.format(record, dest, &mut ctx)?; - Ok(ctx.fmt_info_builder.build()) + Ok(()) } } /// Provides context for patterns. /// /// There is nothing to set up here at the moment, reserved for future use. -#[derive(Clone, Debug)] -pub struct PatternContext { - fmt_info_builder: FmtExtraInfoBuilder, +#[derive(Debug)] +pub struct PatternContext<'a> { + fmt_ctx: &'a mut FormatterContext, } -impl PatternContext { +impl<'a> PatternContext<'a> { /// Creates a new `PatternContext` object. #[must_use] - fn new(fmt_info_builder: FmtExtraInfoBuilder) -> Self { - Self { fmt_info_builder } - } - - /// Sets the style range of the log message written by the patterns. - /// - /// This function is reserved for use by the style range pattern. Other - /// built-in patterns should not use this function. User-defined - /// patterns cannot use this function due to type privacy. - fn set_style_range(&mut self, style_range: Range) { - let builder = std::mem::take(&mut self.fmt_info_builder); - self.fmt_info_builder = builder.style_range(style_range); + fn new(fmt_ctx: &'a mut FormatterContext) -> Self { + Self { fmt_ctx } } } @@ -1196,6 +1191,8 @@ tuple_pattern! { #[cfg(test)] pub mod tests { + use std::ops::Range; + use super::*; use crate::{Level, SourceLocation}; @@ -1217,15 +1214,14 @@ pub mod tests { { let record = get_mock_record(); let mut output = StringBuf::new(); - let mut ctx = PatternContext::new(FmtExtraInfoBuilder::default()); + let mut fmt_ctx = FormatterContext::new(); + let mut pat_ctx = PatternContext::new(&mut fmt_ctx); - let format_result = pattern.format(&record, &mut output, &mut ctx); + let format_result = pattern.format(&record, &mut output, &mut pat_ctx); assert!(format_result.is_ok()); assert_eq!(output.as_str(), formatted.as_ref()); - - let fmt_info = ctx.fmt_info_builder.build(); - assert_eq!(fmt_info.style_range(), style_range); + assert_eq!(fmt_ctx.style_range(), style_range); } #[test] diff --git a/spdlog/src/formatter/pattern_formatter/pattern/full.rs b/spdlog/src/formatter/pattern_formatter/pattern/full.rs index d738034..6953523 100644 --- a/spdlog/src/formatter/pattern_formatter/pattern/full.rs +++ b/spdlog/src/formatter/pattern_formatter/pattern/full.rs @@ -30,13 +30,14 @@ impl Pattern for Full { dest: &mut StringBuf, ctx: &mut PatternContext, ) -> crate::Result<()> { - let extra_info = self.full_formatter.format(record, dest)?; - if let Some(style_range) = extra_info.style_range { - // Before we support multiple style ranges, if there is already a style range - // set, we don't override it. - if ctx.fmt_info_builder.info.style_range.is_none() { - ctx.set_style_range(style_range) - } + let saved_style_range = ctx.fmt_ctx.style_range.clone(); + + self.full_formatter.format(record, dest, ctx.fmt_ctx)?; + + // TODO: Before we support multiple style ranges, if there is already a style + // range set, we don't override it. + if let Some(saved_style_range) = saved_style_range { + ctx.fmt_ctx.set_style_range(Some(saved_style_range)); } Ok(()) } diff --git a/spdlog/src/formatter/pattern_formatter/pattern/style_range.rs b/spdlog/src/formatter/pattern_formatter/pattern/style_range.rs index 82c26d7..906da8d 100644 --- a/spdlog/src/formatter/pattern_formatter/pattern/style_range.rs +++ b/spdlog/src/formatter/pattern_formatter/pattern/style_range.rs @@ -36,7 +36,8 @@ where self.inner.format(record, dest, ctx)?; let style_range_end = dest.len(); - ctx.set_style_range(style_range_start..style_range_end); + ctx.fmt_ctx + .set_style_range(Some(style_range_start..style_range_end)); Ok(()) } diff --git a/spdlog/src/sink/file_sink.rs b/spdlog/src/sink/file_sink.rs index c1e448a..7f3f775 100644 --- a/spdlog/src/sink/file_sink.rs +++ b/spdlog/src/sink/file_sink.rs @@ -8,6 +8,7 @@ use std::{ }; use crate::{ + formatter::FormatterContext, sink::{helper, Sink}, sync::*, utils, Error, Record, Result, StringBuf, @@ -86,10 +87,11 @@ impl FileSink { impl Sink for FileSink { fn log(&self, record: &Record) -> Result<()> { let mut string_buf = StringBuf::new(); + let mut ctx = FormatterContext::new(); self.common_impl .formatter .read() - .format(record, &mut string_buf)?; + .format(record, &mut string_buf, &mut ctx)?; self.file .lock() diff --git a/spdlog/src/sink/journald_sink.rs b/spdlog/src/sink/journald_sink.rs index 168154c..7b0fc57 100644 --- a/spdlog/src/sink/journald_sink.rs +++ b/spdlog/src/sink/journald_sink.rs @@ -1,7 +1,7 @@ use std::{io, os::raw::c_int}; use crate::{ - formatter::JournaldFormatter, + formatter::{FormatterContext, JournaldFormatter}, sink::{helper, Sink}, Error, Level, Record, Result, StdResult, StringBuf, }; @@ -117,10 +117,11 @@ impl JournaldSink { impl Sink for JournaldSink { fn log(&self, record: &Record) -> Result<()> { let mut string_buf = StringBuf::new(); + let mut ctx = FormatterContext::new(); self.common_impl .formatter .read() - .format(record, &mut string_buf)?; + .format(record, &mut string_buf, &mut ctx)?; let kvs = [ format!("MESSAGE={}", string_buf), diff --git a/spdlog/src/sink/rotating_file_sink.rs b/spdlog/src/sink/rotating_file_sink.rs index 05379f3..792c329 100644 --- a/spdlog/src/sink/rotating_file_sink.rs +++ b/spdlog/src/sink/rotating_file_sink.rs @@ -16,6 +16,7 @@ use chrono::prelude::*; use crate::{ error::InvalidArgumentError, + formatter::FormatterContext, sink::{helper, Sink}, sync::*, utils, Error, Record, Result, StringBuf, @@ -230,10 +231,11 @@ impl RotatingFileSink { impl Sink for RotatingFileSink { fn log(&self, record: &Record) -> Result<()> { let mut string_buf = StringBuf::new(); + let mut ctx = FormatterContext::new(); self.common_impl .formatter .read() - .format(record, &mut string_buf)?; + .format(record, &mut string_buf, &mut ctx)?; self.rotator.log(record, &string_buf) } diff --git a/spdlog/src/sink/std_stream_sink.rs b/spdlog/src/sink/std_stream_sink.rs index fc92ed4..a03199d 100644 --- a/spdlog/src/sink/std_stream_sink.rs +++ b/spdlog/src/sink/std_stream_sink.rs @@ -8,6 +8,7 @@ use std::{ use if_chain::if_chain; use crate::{ + formatter::FormatterContext, sink::{helper, Sink}, terminal_style::{LevelStyles, Style, StyleMode}, Error, Level, Record, Result, StringBuf, @@ -161,18 +162,18 @@ impl StdStreamSink { impl Sink for StdStreamSink { fn log(&self, record: &Record) -> Result<()> { let mut string_buf = StringBuf::new(); - let extra_info = self - .common_impl + let mut ctx = FormatterContext::new(); + self.common_impl .formatter .read() - .format(record, &mut string_buf)?; + .format(record, &mut string_buf, &mut ctx)?; let mut dest = self.dest.lock(); (|| { if_chain! { if self.should_render_style; - if let Some(style_range) = extra_info.style_range(); + if let Some(style_range) = ctx.style_range(); then { let style = self.level_styles.style(record.level()); diff --git a/spdlog/src/sink/win_debug_sink.rs b/spdlog/src/sink/win_debug_sink.rs index 70e22b9..79fb45d 100644 --- a/spdlog/src/sink/win_debug_sink.rs +++ b/spdlog/src/sink/win_debug_sink.rs @@ -1,6 +1,7 @@ use std::{ffi::OsStr, iter::once}; use crate::{ + formatter::FormatterContext, sink::{helper, Sink}, Record, Result, StringBuf, }; @@ -48,10 +49,11 @@ impl Sink for WinDebugSink { use std::os::windows::ffi::OsStrExt; let mut string_buf = StringBuf::new(); + let mut ctx = FormatterContext::new(); self.common_impl .formatter .read() - .format(record, &mut string_buf)?; + .format(record, &mut string_buf, &mut ctx)?; let wide: Vec = OsStr::new(&string_buf) .encode_wide() diff --git a/spdlog/src/sink/write_sink.rs b/spdlog/src/sink/write_sink.rs index 16fb899..f14da83 100644 --- a/spdlog/src/sink/write_sink.rs +++ b/spdlog/src/sink/write_sink.rs @@ -1,6 +1,7 @@ use std::{convert::Infallible, io::Write, marker::PhantomData}; use crate::{ + formatter::FormatterContext, sink::{helper, Sink}, sync::*, Error, Record, Result, StringBuf, @@ -100,10 +101,11 @@ where { fn log(&self, record: &Record) -> Result<()> { let mut string_buf = StringBuf::new(); + let mut ctx = FormatterContext::new(); self.common_impl .formatter .read() - .format(record, &mut string_buf)?; + .format(record, &mut string_buf, &mut ctx)?; self.lock_target() .write_all(string_buf.as_bytes()) diff --git a/spdlog/tests/pattern.rs b/spdlog/tests/pattern.rs index a645e2a..301a4ad 100644 --- a/spdlog/tests/pattern.rs +++ b/spdlog/tests/pattern.rs @@ -10,7 +10,7 @@ use regex::Regex; use spdlog::formatter::runtime_pattern; use spdlog::{ error, - formatter::{pattern, Formatter, Pattern, PatternFormatter}, + formatter::{pattern, Formatter, FormatterContext, Pattern, PatternFormatter}, prelude::*, sink::Sink, Error, StringBuf, __EOL, @@ -138,9 +138,12 @@ impl Sink for MockSink { fn log(&self, record: &spdlog::Record) -> spdlog::Result<()> { let mut buf = StringBuf::new(); let fmt = self.formatter.lock().unwrap(); - let extra_info = fmt.as_ref().unwrap().format(record, &mut buf).unwrap(); - *self.last_msg.lock().unwrap() = - Some((String::from(buf.as_str()), extra_info.style_range())); + let mut ctx = FormatterContext::new(); + fmt.as_ref() + .unwrap() + .format(record, &mut buf, &mut ctx) + .unwrap(); + *self.last_msg.lock().unwrap() = Some((String::from(buf.as_str()), ctx.style_range())); Ok(()) }