src/handlers/formatters/format_trait.rs

Lines

100.00 %

Functions

100.00 %

Regions

100.00 %

LineCountSource (jump to first uncovered line)
1
//
2
// File Name:    format_trait.rs
3
// Directory:    src/handlers/formatters
4
// Project Name: flogging
5
//
6
// Copyright (C) 2025 Bradley Willcott
7
//
8
// SPDX-License-Identifier: GPL-3.0-or-later
9
//
10
// This library (crate) is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
14
//
15
// This library (crate) is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
// GNU General Public License for more details.
19
//
20
// You should have received a copy of the GNU General Public License
21
// along with this library (crate).  If not, see <https://www.gnu.org/licenses/>.
22
//
23
24
//!
25
//! # Format Trait
26
//!
27
28
use crate::LogEntry;
29
use dyn_clone::DynClone;
30
use dyn_fmt::AsStrFormatExt;
31
use regex::Regex;
32
use std::{fmt, hash};
33
use strfmt::strfmt;
34
35
///
36
/// Provides methods for formatting [`LogEntry`]s.
37
///
38
pub trait FormatTrait: fmt::Display + DynClone + Send + Sync {
39
    ///
40
    /// Use this method to setup the parameters for calling [`ft_fmt()`][FormatTrait::ft_fmt()].
41
    ///
42
    /// ## Parameters
43
    /// - `log_entry` A reference to the `LogEntry` to be formatted.
44
    ///
45
    /// ## Examples
46
    /// ```text
47
    /// impl FormatTrait for SimpleFormatter {
48
    ///     fn format(&self, log_entry: &LogEntry) -> String {
49
    ///         self.ft_fmt(self.dt_fmt(), self.fmt_string(), log_entry)
50
    ///     }
51
    /// }
52
    /// ```
53
    ///
54
    fn format(&self, log_entry: &LogEntry) -> String;
55
56
    ///
57
    /// This method does the actual formatting of the `log_entry`.
58
    ///
59
    /// ## Parameters
60
    /// - `dt_fmt` - The [`chrono::DateTime`] format string.
61
    /// - `fmt` - The primary format string.\
62
    ///   Available variables:
63
    ///     - `dt` - The datetime formatted with: `dt_fmt`.
64
    ///     - `mod_path` - The module path, possibly supplied via: [`module_path!()`][module_path].
65
    ///     - `fn_name` - The name of the  function/method inside which the log entry
66
    ///       was generated. Supplied by the [`#[logger]`][crate::logger] macro, or manually with the
67
    ///       [`set_fn_name()`][crate::Logger::set_fn_name] method.
68
    ///     - `level` - The log [level][crate::Level] for which the entry was created.
69
    ///     - `message` - The text of the log entry.
70
    ///
71154
    fn ft_fmt(&self, dt_fmt: String, fmt: String, log_entry: &LogEntry) -> String {
72154
        let dt = log_entry.timestamp.format(&dt_fmt).to_string();
73
74154
        strfmt!(
75154
            &fmt,
76154
            dt,
77154
            message => log_entry.message.clone(),
78154
            mod_path =>  log_entry.mod_path.clone(),
79154
            fn_name => log_entry.fn_name.clone(),
80154
            level => log_entry.level.as_str()
81
        )
82154
        .unwrap()
83154
    }
84
}
85
86
dyn_clone::clone_trait_object!(FormatTrait);
87
88
impl fmt::Debug for dyn FormatTrait {
891
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
901
        self.fmt(f)
911
    }
92
}
93
94
#[cfg(test)]
95
mod tests {
96
    use crate::*;
97
    use strfmt::strfmt;
98
    // use chrono::Local;
99
100
    #[test]
1011
    fn strfmt_test() {
1021
        let fmt = "test: {text} - {text2}";
1031
        let text = "Some text";
1041
        let text2 = "Will this work?";
105
1061
        let output = strfmt!(fmt, text2, text).unwrap();
107
1081
        assert_eq!("test: Some text - Will this work?".to_string(), output);
1091
    }
110
111
    // #[test]
112
    // fn format() {
113
    //     let log_entry = LogEntry {
114
    //         timestamp: Local::now(),
115
    //         mod_path: module_path!().to_string(),
116
    //         fn_name: "format".to_string(),
117
    //         level: crate::Level::INFO,
118
    //         message: "We are testing log entry formatting.".to_string(),
119
    //     };
120
121
    //     println! {"{log_entry}"};
122
123
    //     // let formatter =
124
    //     // let text =
125
    // }
126
127
    #[test]
1281
    fn debug() {
1291
        let fmt = FormatType::Custom.create(Some(Box::new(SimpleFormatter::new())));
1301
        println!("fmt: {fmt}");
131
1321
        let sf: Box<dyn FormatTrait> = Box::new(SimpleFormatter::new());
1331
        println!("sf: {sf:?}");
134
1351
        assert_eq!(fmt.to_string(), sf.to_string());
1361
    }
137
}