spdlog/formatter/pattern_formatter/
mod.rs

1#[doc(hidden)]
2#[path = "pattern/mod.rs"]
3pub mod __pattern;
4
5#[cfg(feature = "runtime-pattern")]
6mod runtime;
7
8use std::{fmt::Write, sync::Arc};
9
10use dyn_clone::*;
11#[cfg(feature = "runtime-pattern")]
12pub use runtime::*;
13
14use crate::{
15    formatter::{Formatter, FormatterContext, TimeDate, TimeDateLazyLocked},
16    Error, Record, StringBuf,
17};
18
19#[rustfmt::skip] // rustfmt currently breaks some empty lines if `#[doc = include_str!("xxx")]` exists
20/// Builds a pattern from a template literal string at compile-time.
21///
22/// It accepts inputs in the form:
23///
24/// ```ignore
25/// // This is not exactly a valid declarative macro, just for intuition.
26/// macro_rules! pattern {
27///     ( $template:literal $(,)? ) => {};
28///     ( $template:literal, $( {$$custom:ident} => $ctor:expr ),+ $(,)? ) => {};
29/// }
30/// ```
31///
32/// Examples of valid inputs:
33///
34/// ```
35/// # use spdlog::formatter::pattern;
36/// # #[derive(Default)]
37/// # struct MyPattern;
38/// pattern!("text");
39/// pattern!("current line: {line}{eol}");
40/// pattern!("custom: {$my_pattern}{eol}", {$my_pattern} => MyPattern::default);
41/// ```
42///
43/// Its first argument accepts only a literal string that is known at compile-time.
44/// If you want to build a pattern from a runtime string, use
45/// [`runtime_pattern!`] macro instead.
46///
47/// # Note
48///
49/// The value returned by this macro is implementation details and users should
50/// not access them. If these details are changed in the future, it may not be
51/// considered as a breaking change.
52///
53/// # Basic Usage
54///
55/// In its simplest form, `pattern` receives a **literal** template string and
56/// converts it into a zero-cost pattern:
57/// ```
58/// use spdlog::formatter::{pattern, PatternFormatter};
59///
60/// let formatter = PatternFormatter::new(pattern!("template string"));
61/// ```
62///
63/// # Using Built-in Patterns
64///
65/// A pattern that always outputs a fixed string is boring and useless.
66/// Luckily, the pattern template string can contain placeholders that
67/// represents built-in patterns. For example, to include the log level and
68/// payload in the pattern, we can simply use `{level}` and `{payload}` in the
69/// pattern template string:
70/// ```
71/// # use spdlog::formatter::{pattern, PatternFormatter};
72/// use spdlog::info;
73#[doc = include_str!(concat!(env!("OUT_DIR"), "/test_utils/common_for_doc_test.rs"))]
74///
75/// let formatter = PatternFormatter::new(pattern!("[{level}] {payload}{eol}"));
76/// # let (doctest, sink) = test_utils::echo_logger_from_formatter(formatter, None);
77///
78/// info!(logger: doctest, "Interesting log message");
79/// # assert_eq!(
80/// #     sink.clone_string().replace("\r", ""),
81/// /* Output */ "[info] Interesting log message\n"
82/// # );
83/// ```
84///
85/// Here, `{level}` and `{payload}` are "placeholders" that will be replaced by
86/// the output of the corresponding built-in patterns when formatting log
87/// records.
88///
89/// What if you want to output a literal `{` or `}` character? Simply use `{{`
90/// and `}}`:
91/// ```
92/// # use spdlog::{
93/// #     formatter::{pattern, PatternFormatter},
94/// #     info,
95/// # };
96#[doc = include_str!(concat!(env!("OUT_DIR"), "/test_utils/common_for_doc_test.rs"))]
97/// let formatter = PatternFormatter::new(pattern!("[{{escaped}}] {payload}{eol}"));
98/// # let (doctest, sink) = test_utils::echo_logger_from_formatter(formatter, None);
99///
100/// info!(logger: doctest, "Interesting log message");
101/// # assert_eq!(
102/// #     sink.clone_string().replace("\r", ""),
103/// /* Output */ "[{escaped}] Interesting log message\n"
104/// # );
105/// ```
106///
107/// You can find a full list of all built-in patterns and their corresponding
108/// placeholders at [Appendix](#appendix-a-full-list-of-built-in-patterns)
109/// below.
110///
111/// # Using Style Range
112///
113/// A specific portion of a formatted log message can be specified as "style
114/// range". Formatted text in the style range will be rendered in a different
115/// style by supported sinks. You can use `{^...}` to mark the style range in
116/// the pattern template string:
117/// ```
118/// # use spdlog::{
119/// #     formatter::{pattern, PatternFormatter},
120/// #     info,
121/// # };
122#[doc = include_str!(concat!(env!("OUT_DIR"), "/test_utils/common_for_doc_test.rs"))]
123/// let formatter = PatternFormatter::new(pattern!("{^[{level}]} {payload}{eol}"));
124/// # let (doctest, sink) = test_utils::echo_logger_from_formatter(formatter, None);
125///
126/// info!(logger: doctest, "Interesting log message");
127/// # assert_eq!(
128/// #     sink.clone_string().replace("\r", ""),
129/// /* Output */ "[info] Interesting log message\n"
130/// //            ^^^^^^ <- style range
131/// # );
132/// ```
133/// 
134/// # Using Your Own Patterns
135///
136/// Yes, you can refer your own implementation of [`Pattern`] in the pattern
137/// template string! Let's say you have a struct that implements the
138/// [`Pattern`] trait. To refer `MyPattern` in the pattern template string, you
139/// need to use the extended syntax to associate `MyPattern` with a name so
140/// that `pattern!` can resolve it:
141/// ```
142/// use std::fmt::Write;
143///
144/// use spdlog::{
145///     formatter::{pattern, Pattern, PatternContext, PatternFormatter},
146///     Record, StringBuf, info
147/// };
148#[doc = include_str!(concat!(env!("OUT_DIR"), "/test_utils/common_for_doc_test.rs"))]
149///
150/// #[derive(Default, Clone)]
151/// struct MyPattern;
152///
153/// impl Pattern for MyPattern {
154///     fn format(&self, record: &Record, dest: &mut StringBuf, _: &mut PatternContext) -> spdlog::Result<()> {
155///         write!(dest, "My own pattern").map_err(spdlog::Error::FormatRecord)
156///     }
157/// }
158///
159/// let pat = pattern!("[{level}] {payload} - {$mypat}{eol}",
160///     {$mypat} => MyPattern::default,
161/// );
162/// let formatter = PatternFormatter::new(pat);
163/// # let (doctest, sink) = test_utils::echo_logger_from_formatter(formatter, None);
164///
165/// info!(logger: doctest, "Interesting log message");
166/// # assert_eq!(
167/// #   sink.clone_string().replace("\r", ""),
168/// /* Output */ "[info] Interesting log message - My own pattern\n"
169/// # );
170/// ```
171///
172/// Note the special `{$name} => id` syntax given to the `pattern` macro.
173/// `name` is the name of your own pattern; placeholder `{$name}` in the
174/// template string will be replaced by the output of your own pattern. `name`
175/// can only be an identifier. `id` is a [path] that identifies a **function**
176/// that can be called with **no arguments**. Instances of your own pattern
177/// will be created by calling this function with no arguments.
178///
179/// [path]: https://doc.rust-lang.org/stable/reference/paths.html
180///
181/// ## Custom Pattern Creation
182///
183/// Each placeholder results in a new pattern instance. For example, consider a
184/// custom pattern that writes a unique ID to the output. If the pattern
185/// template string contains multiple placeholders that refer to `MyPattern`,
186/// each placeholder will eventually be replaced by different IDs.
187///
188/// ```
189/// # use std::{
190/// #     fmt::Write,
191/// #     sync::atomic::{AtomicU32, Ordering},
192/// # };
193/// # use spdlog::{
194/// #     formatter::{pattern, Pattern, PatternContext, PatternFormatter},
195/// #     prelude::*,
196/// #     Record, StringBuf,
197/// # };
198#[doc = include_str!(concat!(env!("OUT_DIR"), "/test_utils/common_for_doc_test.rs"))]
199/// static NEXT_ID: AtomicU32 = AtomicU32::new(0);
200///
201/// #[derive(Clone)]
202/// struct MyPattern {
203///     id: u32,
204/// }
205///
206/// impl MyPattern {
207///     fn new() -> Self {
208///         Self {
209///             id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
210///         }
211///     }
212/// }
213///
214/// impl Pattern for MyPattern {
215///     fn format(&self, record: &Record, dest: &mut StringBuf, _: &mut PatternContext) -> spdlog::Result<()> {
216///         write!(dest, "{}", self.id).map_err(spdlog::Error::FormatRecord)
217///     }
218/// }
219///
220/// let pat = pattern!("[{level}] {payload} - {$mypat} {$mypat} {$mypat}{eol}",
221///     {$mypat} => MyPattern::new,
222/// );
223/// let formatter = PatternFormatter::new(pat);
224/// # let (doctest, sink) = test_utils::echo_logger_from_formatter(formatter, None);
225///
226/// info!(logger: doctest, "Interesting log message");
227/// # assert_eq!(
228/// #   sink.clone_string().replace("\r", ""),
229/// /* Output */ "[info] Interesting log message - 0 1 2\n"
230/// # );
231/// ```
232///
233/// Of course, you can have multiple custom patterns:
234/// ```
235/// # use spdlog::formatter::pattern;
236/// #
237/// # #[derive(Default)]
238/// # struct MyPattern;
239/// # #[derive(Default)]
240/// # struct MyOtherPattern;
241/// #
242/// let pat = pattern!("[{level}] {payload} - {$mypat} {$myotherpat}{eol}",
243///     {$mypat} => MyPattern::default,
244///     {$myotherpat} => MyOtherPattern::default,
245/// );
246/// ```
247///
248/// ## Name Conflicts are Hard Errors
249///
250/// It's a hard error if names of your own custom pattern conflicts with other
251/// patterns:
252///
253/// ```compile_fail
254/// # use spdlog::formatter::pattern;
255/// #
256/// # #[derive(Default)]
257/// # struct MyPattern;
258/// # #[derive(Default)]
259/// # struct MyOtherPattern;
260/// #
261/// let pattern = pattern!("[{level}] {payload} - {$mypat}{eol}",
262///     {$mypat} => MyPattern::new,
263///     // Error: name conflicts with another custom pattern
264///     {$mypat} => MyOtherPattern::new,
265/// );
266/// ```
267///
268/// ```compile_fail
269/// # use spdlog::formatter::pattern;
270/// #
271/// # #[derive(Default)]
272/// # struct MyPattern;
273/// #
274/// let pattern = pattern!("[{level}] {payload} - {$day}{eol}",
275///     // Error: name conflicts with a built-in pattern
276///     {$day} => MyPattern::new,
277/// );
278/// ```
279///
280/// # Appendix: Full List of Built-in Patterns
281///
282/// | Placeholders          | Description                  | Example                                      |
283/// | --------------------- | ---------------------------- | -------------------------------------------- |
284/// | `{weekday_name}`      | Abbreviated weekday name     | `Mon`, `Tue`                                 |
285/// | `{weekday_name_full}` | Weekday name                 | `Monday`, `Tuesday`                          |
286/// | `{month_name}`        | Abbreviated month name       | `Jan`, `Feb`                                 |
287/// | `{month_name_full}`   | Month name                   | `January`, `February`                        |
288/// | `{datetime}`          | Full date time               | `Thu Aug 23 15:35:46 2014`                   |
289/// | `{year_short}`        | Short year                   | `22`, `20`                                   |
290/// | `{year}`              | Year                         | `2022`, `2021`                               |
291/// | `{date_short}`        | Short date                   | `04/01/22`, `12/31/21`                       |
292/// | `{date}`              | Date (ISO 8601)              | `2022-04-01`, `2021-12-31`                   |
293/// | `{month}`             | Month                        | `01`, `12`                                   |
294/// | `{day}`               | Day in month                 | `01`, `12`, `31`, `30`                       |
295/// | `{hour}`              | Hour in 24-hour              | `01`, `12`, `23`                             |
296/// | `{hour_12}`           | Hour in 12-hour              | `01`, `12`                                   |
297/// | `{minute}`            | Minute                       | `00`, `05`, `59`                             |
298/// | `{second}`            | Second                       | `00`, `05`, `59`                             |
299/// | `{millisecond}`       | Millisecond                  | `231`                                        |
300/// | `{microsecond}`       | Microseconds within a second | `372152`                                     |
301/// | `{nanosecond}`        | Nanoseconds within a second  | `482930154`                                  |
302/// | `{am_pm}`             | AM / PM                      | `AM`, `PM`                                   |
303/// | `{time_12}`           | Time in 12-hour format       | `02:55:02 PM`                                |
304/// | `{time_short}`        | Short time                   | `22:28`, `09:53`                             |
305/// | `{time}`              | Time                         | `22:28:02`, `09:53:41`                       |
306/// | `{tz_offset}`         | Timezone offset              | `+08:00`, `+00:00`, `-06:00`                 |
307/// | `{unix_timestamp}`    | Unix timestamp               | `1528834770`                                 |
308/// | `{full}`              | Full log message             | See [`FullFormatter`]                        |
309/// | `{level}`             | Log level                    | `critical`, `error`, `warn`                  |
310/// | `{level_short}`       | Short log level              | `C`, `E`, `W`                                |
311/// | `{source}`            | Source file and line         | `path/to/main.rs:30` [^1]                    |
312/// | `{file_name}`         | Source file name             | `main.rs` [^1]                               |
313/// | `{file}`              | Source file path             | `path/to/main.rs` [^1]                       |
314/// | `{line}`              | Source file line             | `30` [^1]                                    |
315/// | `{column}`            | Source file column           | `20` [^1]                                    |
316/// | `{module_path}`       | Source module path           | `mod::module` [^1]                           |
317/// | `{logger}`            | Logger name                  | `my-logger`                                  |
318/// | `{payload}`           | Log payload                  | `log message`                                |
319/// | `{kv}`                | Key-values                   | `k1=123 k2=text`                             |
320/// | `{pid}`               | Process ID                   | `3824`                                       |
321/// | `{tid}`               | Thread ID                    | `3132`                                       |
322/// | `{eol}`               | End of line                  | `\n` (on non-Windows) or `\r\n` (on Windows) |
323/// 
324/// [^1]: Patterns related to source location require that feature
325///       `source-location` is enabled, otherwise the output is empty.
326///
327/// [`runtime_pattern!`]: crate::formatter::runtime_pattern
328/// [`FullFormatter`]: crate::formatter::FullFormatter
329pub use ::spdlog_macros::pattern;
330
331// Emit a compile error if the feature is not enabled.
332#[cfg(not(feature = "runtime-pattern"))]
333pub use crate::__runtime_pattern_disabled as runtime_pattern;
334
335#[cfg(not(feature = "runtime-pattern"))]
336#[doc(hidden)]
337#[macro_export]
338macro_rules! __runtime_pattern_disabled {
339    ($($_:tt)*) => {
340        compile_error!(
341            "macro `runtime_pattern` required to enable crate feature `runtime-pattern` for spdlog-rs"
342        );
343    };
344}
345
346/// Formats logs according to a specified pattern.
347#[derive(Clone)]
348pub struct PatternFormatter<P> {
349    pattern: P,
350}
351
352impl<P> PatternFormatter<P>
353where
354    P: Pattern,
355{
356    /// Creates a new `PatternFormatter` object with the given pattern.
357    ///
358    /// Currently users can only create a `pattern` object by using:
359    ///
360    /// - Macro [`pattern!`] to build a pattern with a literal template string
361    ///   at compile-time.
362    /// - Macro [`runtime_pattern!`] to build a pattern at runtime.
363    #[must_use]
364    pub fn new(pattern: P) -> Self {
365        Self { pattern }
366    }
367}
368
369impl<P> Formatter for PatternFormatter<P>
370where
371    P: 'static + Clone + Pattern,
372{
373    fn format(
374        &self,
375        record: &Record,
376        dest: &mut StringBuf,
377        fmt_ctx: &mut FormatterContext,
378    ) -> crate::Result<()> {
379        #[cfg(not(feature = "flexible-string"))]
380        dest.reserve(crate::string_buf::RESERVE_SIZE);
381
382        fmt_ctx.locked_time_date = Some(TimeDateLazyLocked::new(record.time()));
383        {
384            let mut pat_ctx = PatternContext { fmt_ctx };
385            self.pattern.format(record, dest, &mut pat_ctx)?;
386        }
387        fmt_ctx.locked_time_date = None;
388        Ok(())
389    }
390}
391
392/// Provides context for patterns.
393///
394/// There is nothing to set up here at the moment, reserved for future use.
395#[derive(Debug)]
396pub struct PatternContext<'a, 'b> {
397    fmt_ctx: &'a mut FormatterContext<'b>,
398}
399
400impl PatternContext<'_, '_> {
401    #[must_use]
402    fn time_date(&mut self) -> TimeDate<'_> {
403        self.fmt_ctx.locked_time_date.as_mut().unwrap().get()
404    }
405}
406
407/// Represents a pattern for replacing a placeholder in templates.
408///
409/// A pattern will be used to replace placeholders that appear in a template
410/// string. Multiple patterns can form a new pattern. The [`PatternFormatter`]
411/// formats logs according to a given pattern.
412///
413/// # Built-in Patterns
414///
415/// `spdlog-rs` provides a rich set of built-in patterns. See the [`pattern`]
416/// macro.
417///
418/// # Custom Patterns
419///
420/// There are 3 approaches to create your own pattern:
421/// - Define a new type and implement this trait;
422/// - Use [`pattern`] macro to create a pattern from a literal template string.
423/// - Use [`runtime_pattern`] macro to create a pattern from a runtime template
424///   string.
425pub trait Pattern: Send + Sync + DynClone {
426    /// Format this pattern against the given log record and write the formatted
427    /// message into the output buffer.
428    ///
429    /// **For implementors:** the `ctx` parameter is reserved for future use.
430    /// For now, please ignore it.
431    fn format(
432        &self,
433        record: &Record,
434        dest: &mut StringBuf,
435        ctx: &mut PatternContext,
436    ) -> crate::Result<()>;
437}
438clone_trait_object!(Pattern);
439
440impl Pattern for String {
441    fn format(
442        &self,
443        record: &Record,
444        dest: &mut StringBuf,
445        ctx: &mut PatternContext,
446    ) -> crate::Result<()> {
447        <&str as Pattern>::format(&&**self, record, dest, ctx)
448    }
449}
450
451impl Pattern for str {
452    fn format(
453        &self,
454        _record: &Record,
455        dest: &mut StringBuf,
456        _ctx: &mut PatternContext,
457    ) -> crate::Result<()> {
458        dest.write_str(self).map_err(Error::FormatRecord)
459    }
460}
461
462impl<T> Pattern for &T
463where
464    T: ?Sized + Pattern,
465{
466    fn format(
467        &self,
468        record: &Record,
469        dest: &mut StringBuf,
470        ctx: &mut PatternContext,
471    ) -> crate::Result<()> {
472        <T as Pattern>::format(*self, record, dest, ctx)
473    }
474}
475
476impl<T> Pattern for Box<T>
477where
478    T: ?Sized + Pattern,
479    Self: Clone,
480{
481    fn format(
482        &self,
483        record: &Record,
484        dest: &mut StringBuf,
485        ctx: &mut PatternContext,
486    ) -> crate::Result<()> {
487        <T as Pattern>::format(&**self, record, dest, ctx)
488    }
489}
490
491impl<T> Pattern for Arc<T>
492where
493    T: ?Sized + Pattern,
494    Self: Clone,
495{
496    fn format(
497        &self,
498        record: &Record,
499        dest: &mut StringBuf,
500        ctx: &mut PatternContext,
501    ) -> crate::Result<()> {
502        <T as Pattern>::format(&**self, record, dest, ctx)
503    }
504}
505
506impl<T> Pattern for &[T]
507where
508    T: Pattern,
509    Self: Clone,
510{
511    fn format(
512        &self,
513        record: &Record,
514        dest: &mut StringBuf,
515        ctx: &mut PatternContext,
516    ) -> crate::Result<()> {
517        for p in *self {
518            <T as Pattern>::format(p, record, dest, ctx)?;
519        }
520        Ok(())
521    }
522}
523
524impl<T, const N: usize> Pattern for [T; N]
525where
526    T: Pattern,
527    Self: Clone,
528{
529    fn format(
530        &self,
531        record: &Record,
532        dest: &mut StringBuf,
533        ctx: &mut PatternContext,
534    ) -> crate::Result<()> {
535        for p in self {
536            <T as Pattern>::format(p, record, dest, ctx)?;
537        }
538        Ok(())
539    }
540}
541
542impl<T> Pattern for Vec<T>
543where
544    T: Pattern,
545    Self: Clone,
546{
547    fn format(
548        &self,
549        record: &Record,
550        dest: &mut StringBuf,
551        ctx: &mut PatternContext,
552    ) -> crate::Result<()> {
553        for p in self {
554            <T as Pattern>::format(p, record, dest, ctx)?;
555        }
556        Ok(())
557    }
558}
559
560macro_rules! last {
561    ( $a:tt, ) => { $a };
562    ( $a:tt, $($rest:tt,)+ ) => { last!($($rest,)+) };
563}
564
565macro_rules! tuple_pattern {
566    (
567        $(
568            $Tuple:ident {
569                $(
570                    ($idx:tt) -> $T:ident
571                )+
572            }
573        )+
574    ) => {
575        $(
576            impl<$($T,)+> Pattern for ($($T,)+)
577            where
578                $($T : Pattern,)+
579                last!($($T,)+) : ?Sized,
580                Self: Clone,
581            {
582                fn format(&self, record: &Record, dest: &mut StringBuf, ctx: &mut PatternContext) -> crate::Result<()> {
583                    $(
584                        <$T as Pattern>::format(&self.$idx, record, dest, ctx)?;
585                    )+
586                    Ok(())
587                }
588            }
589        )+
590    };
591}
592
593impl Pattern for () {
594    fn format(
595        &self,
596        _record: &Record,
597        _dest: &mut StringBuf,
598        _ctx: &mut PatternContext,
599    ) -> crate::Result<()> {
600        Ok(())
601    }
602}
603
604tuple_pattern! {
605    Tuple1 {
606        (0) -> T0
607    }
608    Tuple2 {
609        (0) -> T0
610        (1) -> T1
611    }
612    Tuple3 {
613        (0) -> T0
614        (1) -> T1
615        (2) -> T2
616    }
617    Tuple4 {
618        (0) -> T0
619        (1) -> T1
620        (2) -> T2
621        (3) -> T3
622    }
623    Tuple5 {
624        (0) -> T0
625        (1) -> T1
626        (2) -> T2
627        (3) -> T3
628        (4) -> T4
629    }
630    Tuple6 {
631        (0) -> T0
632        (1) -> T1
633        (2) -> T2
634        (3) -> T3
635        (4) -> T4
636        (5) -> T5
637    }
638    Tuple7 {
639        (0) -> T0
640        (1) -> T1
641        (2) -> T2
642        (3) -> T3
643        (4) -> T4
644        (5) -> T5
645        (6) -> T6
646    }
647    Tuple8 {
648        (0) -> T0
649        (1) -> T1
650        (2) -> T2
651        (3) -> T3
652        (4) -> T4
653        (5) -> T5
654        (6) -> T6
655        (7) -> T7
656    }
657    Tuple9 {
658        (0) -> T0
659        (1) -> T1
660        (2) -> T2
661        (3) -> T3
662        (4) -> T4
663        (5) -> T5
664        (6) -> T6
665        (7) -> T7
666        (8) -> T8
667    }
668    Tuple10 {
669        (0) -> T0
670        (1) -> T1
671        (2) -> T2
672        (3) -> T3
673        (4) -> T4
674        (5) -> T5
675        (6) -> T6
676        (7) -> T7
677        (8) -> T8
678        (9) -> T9
679    }
680    Tuple11 {
681        (0) -> T0
682        (1) -> T1
683        (2) -> T2
684        (3) -> T3
685        (4) -> T4
686        (5) -> T5
687        (6) -> T6
688        (7) -> T7
689        (8) -> T8
690        (9) -> T9
691        (10) -> T10
692    }
693    Tuple12 {
694        (0) -> T0
695        (1) -> T1
696        (2) -> T2
697        (3) -> T3
698        (4) -> T4
699        (5) -> T5
700        (6) -> T6
701        (7) -> T7
702        (8) -> T8
703        (9) -> T9
704        (10) -> T10
705        (11) -> T11
706    }
707    Tuple13 {
708        (0) -> T0
709        (1) -> T1
710        (2) -> T2
711        (3) -> T3
712        (4) -> T4
713        (5) -> T5
714        (6) -> T6
715        (7) -> T7
716        (8) -> T8
717        (9) -> T9
718        (10) -> T10
719        (11) -> T11
720        (12) -> T12
721    }
722    Tuple14 {
723        (0) -> T0
724        (1) -> T1
725        (2) -> T2
726        (3) -> T3
727        (4) -> T4
728        (5) -> T5
729        (6) -> T6
730        (7) -> T7
731        (8) -> T8
732        (9) -> T9
733        (10) -> T10
734        (11) -> T11
735        (12) -> T12
736        (13) -> T13
737    }
738    Tuple15 {
739        (0) -> T0
740        (1) -> T1
741        (2) -> T2
742        (3) -> T3
743        (4) -> T4
744        (5) -> T5
745        (6) -> T6
746        (7) -> T7
747        (8) -> T8
748        (9) -> T9
749        (10) -> T10
750        (11) -> T11
751        (12) -> T12
752        (13) -> T13
753        (14) -> T14
754    }
755    Tuple16 {
756        (0) -> T0
757        (1) -> T1
758        (2) -> T2
759        (3) -> T3
760        (4) -> T4
761        (5) -> T5
762        (6) -> T6
763        (7) -> T7
764        (8) -> T8
765        (9) -> T9
766        (10) -> T10
767        (11) -> T11
768        (12) -> T12
769        (13) -> T13
770        (14) -> T14
771        (15) -> T15
772    }
773    Tuple17 {
774        (0) -> T0
775        (1) -> T1
776        (2) -> T2
777        (3) -> T3
778        (4) -> T4
779        (5) -> T5
780        (6) -> T6
781        (7) -> T7
782        (8) -> T8
783        (9) -> T9
784        (10) -> T10
785        (11) -> T11
786        (12) -> T12
787        (13) -> T13
788        (14) -> T14
789        (15) -> T15
790        (16) -> T16
791    }
792    Tuple18 {
793        (0) -> T0
794        (1) -> T1
795        (2) -> T2
796        (3) -> T3
797        (4) -> T4
798        (5) -> T5
799        (6) -> T6
800        (7) -> T7
801        (8) -> T8
802        (9) -> T9
803        (10) -> T10
804        (11) -> T11
805        (12) -> T12
806        (13) -> T13
807        (14) -> T14
808        (15) -> T15
809        (16) -> T16
810        (17) -> T17
811    }
812    Tuple19 {
813        (0) -> T0
814        (1) -> T1
815        (2) -> T2
816        (3) -> T3
817        (4) -> T4
818        (5) -> T5
819        (6) -> T6
820        (7) -> T7
821        (8) -> T8
822        (9) -> T9
823        (10) -> T10
824        (11) -> T11
825        (12) -> T12
826        (13) -> T13
827        (14) -> T14
828        (15) -> T15
829        (16) -> T16
830        (17) -> T17
831        (18) -> T18
832    }
833    Tuple20 {
834        (0) -> T0
835        (1) -> T1
836        (2) -> T2
837        (3) -> T3
838        (4) -> T4
839        (5) -> T5
840        (6) -> T6
841        (7) -> T7
842        (8) -> T8
843        (9) -> T9
844        (10) -> T10
845        (11) -> T11
846        (12) -> T12
847        (13) -> T13
848        (14) -> T14
849        (15) -> T15
850        (16) -> T16
851        (17) -> T17
852        (18) -> T18
853        (19) -> T19
854    }
855    Tuple21 {
856        (0) -> T0
857        (1) -> T1
858        (2) -> T2
859        (3) -> T3
860        (4) -> T4
861        (5) -> T5
862        (6) -> T6
863        (7) -> T7
864        (8) -> T8
865        (9) -> T9
866        (10) -> T10
867        (11) -> T11
868        (12) -> T12
869        (13) -> T13
870        (14) -> T14
871        (15) -> T15
872        (16) -> T16
873        (17) -> T17
874        (18) -> T18
875        (19) -> T19
876        (20) -> T20
877    }
878    Tuple22 {
879        (0) -> T0
880        (1) -> T1
881        (2) -> T2
882        (3) -> T3
883        (4) -> T4
884        (5) -> T5
885        (6) -> T6
886        (7) -> T7
887        (8) -> T8
888        (9) -> T9
889        (10) -> T10
890        (11) -> T11
891        (12) -> T12
892        (13) -> T13
893        (14) -> T14
894        (15) -> T15
895        (16) -> T16
896        (17) -> T17
897        (18) -> T18
898        (19) -> T19
899        (20) -> T20
900        (21) -> T21
901    }
902    Tuple23 {
903        (0) -> T0
904        (1) -> T1
905        (2) -> T2
906        (3) -> T3
907        (4) -> T4
908        (5) -> T5
909        (6) -> T6
910        (7) -> T7
911        (8) -> T8
912        (9) -> T9
913        (10) -> T10
914        (11) -> T11
915        (12) -> T12
916        (13) -> T13
917        (14) -> T14
918        (15) -> T15
919        (16) -> T16
920        (17) -> T17
921        (18) -> T18
922        (19) -> T19
923        (20) -> T20
924        (21) -> T21
925        (22) -> T22
926    }
927    Tuple24 {
928        (0) -> T0
929        (1) -> T1
930        (2) -> T2
931        (3) -> T3
932        (4) -> T4
933        (5) -> T5
934        (6) -> T6
935        (7) -> T7
936        (8) -> T8
937        (9) -> T9
938        (10) -> T10
939        (11) -> T11
940        (12) -> T12
941        (13) -> T13
942        (14) -> T14
943        (15) -> T15
944        (16) -> T16
945        (17) -> T17
946        (18) -> T18
947        (19) -> T19
948        (20) -> T20
949        (21) -> T21
950        (22) -> T22
951        (23) -> T23
952    }
953    Tuple25 {
954        (0) -> T0
955        (1) -> T1
956        (2) -> T2
957        (3) -> T3
958        (4) -> T4
959        (5) -> T5
960        (6) -> T6
961        (7) -> T7
962        (8) -> T8
963        (9) -> T9
964        (10) -> T10
965        (11) -> T11
966        (12) -> T12
967        (13) -> T13
968        (14) -> T14
969        (15) -> T15
970        (16) -> T16
971        (17) -> T17
972        (18) -> T18
973        (19) -> T19
974        (20) -> T20
975        (21) -> T21
976        (22) -> T22
977        (23) -> T23
978        (24) -> T24
979    }
980    Tuple26 {
981        (0) -> T0
982        (1) -> T1
983        (2) -> T2
984        (3) -> T3
985        (4) -> T4
986        (5) -> T5
987        (6) -> T6
988        (7) -> T7
989        (8) -> T8
990        (9) -> T9
991        (10) -> T10
992        (11) -> T11
993        (12) -> T12
994        (13) -> T13
995        (14) -> T14
996        (15) -> T15
997        (16) -> T16
998        (17) -> T17
999        (18) -> T18
1000        (19) -> T19
1001        (20) -> T20
1002        (21) -> T21
1003        (22) -> T22
1004        (23) -> T23
1005        (24) -> T24
1006        (25) -> T25
1007    }
1008    Tuple27 {
1009        (0) -> T0
1010        (1) -> T1
1011        (2) -> T2
1012        (3) -> T3
1013        (4) -> T4
1014        (5) -> T5
1015        (6) -> T6
1016        (7) -> T7
1017        (8) -> T8
1018        (9) -> T9
1019        (10) -> T10
1020        (11) -> T11
1021        (12) -> T12
1022        (13) -> T13
1023        (14) -> T14
1024        (15) -> T15
1025        (16) -> T16
1026        (17) -> T17
1027        (18) -> T18
1028        (19) -> T19
1029        (20) -> T20
1030        (21) -> T21
1031        (22) -> T22
1032        (23) -> T23
1033        (24) -> T24
1034        (25) -> T25
1035        (26) -> T26
1036    }
1037    Tuple28 {
1038        (0) -> T0
1039        (1) -> T1
1040        (2) -> T2
1041        (3) -> T3
1042        (4) -> T4
1043        (5) -> T5
1044        (6) -> T6
1045        (7) -> T7
1046        (8) -> T8
1047        (9) -> T9
1048        (10) -> T10
1049        (11) -> T11
1050        (12) -> T12
1051        (13) -> T13
1052        (14) -> T14
1053        (15) -> T15
1054        (16) -> T16
1055        (17) -> T17
1056        (18) -> T18
1057        (19) -> T19
1058        (20) -> T20
1059        (21) -> T21
1060        (22) -> T22
1061        (23) -> T23
1062        (24) -> T24
1063        (25) -> T25
1064        (26) -> T26
1065        (27) -> T27
1066    }
1067    Tuple29 {
1068        (0) -> T0
1069        (1) -> T1
1070        (2) -> T2
1071        (3) -> T3
1072        (4) -> T4
1073        (5) -> T5
1074        (6) -> T6
1075        (7) -> T7
1076        (8) -> T8
1077        (9) -> T9
1078        (10) -> T10
1079        (11) -> T11
1080        (12) -> T12
1081        (13) -> T13
1082        (14) -> T14
1083        (15) -> T15
1084        (16) -> T16
1085        (17) -> T17
1086        (18) -> T18
1087        (19) -> T19
1088        (20) -> T20
1089        (21) -> T21
1090        (22) -> T22
1091        (23) -> T23
1092        (24) -> T24
1093        (25) -> T25
1094        (26) -> T26
1095        (27) -> T27
1096        (28) -> T28
1097    }
1098    Tuple30 {
1099        (0) -> T0
1100        (1) -> T1
1101        (2) -> T2
1102        (3) -> T3
1103        (4) -> T4
1104        (5) -> T5
1105        (6) -> T6
1106        (7) -> T7
1107        (8) -> T8
1108        (9) -> T9
1109        (10) -> T10
1110        (11) -> T11
1111        (12) -> T12
1112        (13) -> T13
1113        (14) -> T14
1114        (15) -> T15
1115        (16) -> T16
1116        (17) -> T17
1117        (18) -> T18
1118        (19) -> T19
1119        (20) -> T20
1120        (21) -> T21
1121        (22) -> T22
1122        (23) -> T23
1123        (24) -> T24
1124        (25) -> T25
1125        (26) -> T26
1126        (27) -> T27
1127        (28) -> T28
1128        (29) -> T29
1129    }
1130    Tuple31 {
1131        (0) -> T0
1132        (1) -> T1
1133        (2) -> T2
1134        (3) -> T3
1135        (4) -> T4
1136        (5) -> T5
1137        (6) -> T6
1138        (7) -> T7
1139        (8) -> T8
1140        (9) -> T9
1141        (10) -> T10
1142        (11) -> T11
1143        (12) -> T12
1144        (13) -> T13
1145        (14) -> T14
1146        (15) -> T15
1147        (16) -> T16
1148        (17) -> T17
1149        (18) -> T18
1150        (19) -> T19
1151        (20) -> T20
1152        (21) -> T21
1153        (22) -> T22
1154        (23) -> T23
1155        (24) -> T24
1156        (25) -> T25
1157        (26) -> T26
1158        (27) -> T27
1159        (28) -> T28
1160        (29) -> T29
1161        (30) -> T30
1162    }
1163    Tuple32 {
1164        (0) -> T0
1165        (1) -> T1
1166        (2) -> T2
1167        (3) -> T3
1168        (4) -> T4
1169        (5) -> T5
1170        (6) -> T6
1171        (7) -> T7
1172        (8) -> T8
1173        (9) -> T9
1174        (10) -> T10
1175        (11) -> T11
1176        (12) -> T12
1177        (13) -> T13
1178        (14) -> T14
1179        (15) -> T15
1180        (16) -> T16
1181        (17) -> T17
1182        (18) -> T18
1183        (19) -> T19
1184        (20) -> T20
1185        (21) -> T21
1186        (22) -> T22
1187        (23) -> T23
1188        (24) -> T24
1189        (25) -> T25
1190        (26) -> T26
1191        (27) -> T27
1192        (28) -> T28
1193        (29) -> T29
1194        (30) -> T30
1195        (31) -> T31
1196    }
1197}
1198
1199#[cfg(test)]
1200mod tests {
1201    use std::ops::Range;
1202
1203    use super::*;
1204    use crate::{Level, SourceLocation};
1205
1206    // We use `get_mock_record` and `test_pattern` in tests/pattern.rs so let's make
1207    // them pub in test builds.
1208
1209    #[must_use]
1210    fn get_mock_record() -> Record<'static> {
1211        Record::new(
1212            Level::Info,
1213            "record_payload",
1214            Some(SourceLocation::__new("module", "file", 10, 20)),
1215            Some("logger_name"),
1216            &[],
1217        )
1218    }
1219
1220    fn test_pattern<P, T>(pattern: P, formatted: T, style_range: Option<Range<usize>>)
1221    where
1222        P: Pattern,
1223        T: AsRef<str>,
1224    {
1225        let record = get_mock_record();
1226        let mut output = StringBuf::new();
1227        let mut fmt_ctx = FormatterContext::new();
1228        fmt_ctx.locked_time_date = Some(TimeDateLazyLocked::new(record.time()));
1229        let mut pat_ctx = PatternContext {
1230            fmt_ctx: &mut fmt_ctx,
1231        };
1232        pattern.format(&record, &mut output, &mut pat_ctx).unwrap();
1233        fmt_ctx.locked_time_date = None;
1234
1235        assert_eq!(output.as_str(), formatted.as_ref());
1236        assert_eq!(fmt_ctx.style_range(), style_range);
1237    }
1238
1239    #[test]
1240    fn test_string_as_pattern() {
1241        test_pattern(String::from("literal"), "literal", None);
1242    }
1243
1244    #[test]
1245    fn test_str_as_pattern() {
1246        test_pattern("literal", "literal", None);
1247    }
1248
1249    #[test]
1250    fn test_pattern_ref_as_pattern() {
1251        #[allow(unknown_lints)]
1252        #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
1253        test_pattern(&String::from("literal"), "literal", None);
1254    }
1255
1256    #[test]
1257    fn test_pattern_mut_as_pattern() {
1258        // Since we now require `T: Pattern` to implement `Clone`, there is no way to
1259        // accept an `&mut T` as a `Pattern` anymore, since `&mut T` is not cloneable.
1260        //
1261        // test_pattern(&mut String::from("literal"), "literal", None);
1262        #[allow(clippy::deref_addrof)]
1263        test_pattern(&*&mut String::from("literal"), "literal", None);
1264    }
1265
1266    #[test]
1267    fn test_box_as_pattern() {
1268        test_pattern(Box::new(String::from("literal")), "literal", None);
1269    }
1270
1271    #[test]
1272    fn test_arc_as_pattern() {
1273        test_pattern(Arc::new(String::from("literal")), "literal", None);
1274    }
1275
1276    #[test]
1277    fn test_slice_as_pattern() {
1278        let pat: &[String] = &[String::from("literal1"), String::from("literal2")];
1279        test_pattern(pat, "literal1literal2", None);
1280    }
1281
1282    #[test]
1283    fn test_empty_slice_as_pattern() {
1284        let pat: &[String] = &[];
1285        test_pattern(pat, "", None);
1286    }
1287
1288    #[test]
1289    fn test_array_as_pattern() {
1290        let pat: [String; 3] = [
1291            String::from("literal1"),
1292            String::from("literal2"),
1293            String::from("literal3"),
1294        ];
1295        test_pattern(pat, "literal1literal2literal3", None);
1296    }
1297
1298    #[test]
1299    fn test_empty_array_as_pattern() {
1300        let pat: [String; 0] = [];
1301        test_pattern(pat, "", None);
1302    }
1303
1304    #[test]
1305    fn test_vec_as_pattern() {
1306        let pat = vec![
1307            String::from("literal1"),
1308            String::from("literal2"),
1309            String::from("literal3"),
1310        ];
1311        test_pattern(pat, "literal1literal2literal3", None);
1312    }
1313
1314    #[test]
1315    fn test_empty_vec_as_pattern() {
1316        let pat: Vec<String> = vec![];
1317        test_pattern(pat, "", None);
1318    }
1319
1320    #[test]
1321    fn test_tuple_as_pattern() {
1322        let pat = (
1323            String::from("literal1"),
1324            "literal2",
1325            String::from("literal3"),
1326        );
1327        test_pattern(pat, "literal1literal2literal3", None);
1328    }
1329
1330    #[test]
1331    fn test_unit_as_pattern() {
1332        test_pattern((), "", None);
1333    }
1334}