q_debug/
fmt.rs

1use crate::logging::LogLocation;
2use chrono::prelude::*;
3use std::fmt::Debug;
4
5// TODO: Configurable options e.g. separator characters, line numbers
6// colours e.t.c
7#[derive(Debug)]
8pub struct Formatter {}
9
10impl Formatter {
11    pub fn header(&self, now: &DateTime<Utc>, log_location: &LogLocation) -> String {
12        format!(
13            "[{} {:?} {} {}:{}]",
14            now.time().format("%H:%M:%S").to_string(),
15            log_location.thread_id,
16            log_location.file_path,
17            log_location.func_path,
18            log_location.lineno
19        )
20    }
21
22    pub fn q(&self) -> String {
23        format!(">")
24    }
25
26    /// Returns a log line for a literal value, `val`.
27    ///
28    /// ```
29    /// use q_debug::fmt::Formatter;
30    ///
31    /// let fmt = Formatter {};
32    ///
33    /// assert_eq!(
34    ///     fmt.q_literal(&String::from("Test message")),
35    ///     String::from("> \"Test message\"")
36    /// );
37    ///
38    /// assert_eq!(
39    ///     fmt.q_literal(&Some(42)),
40    ///     String::from("> Some(42)")
41    /// );
42    /// ```
43    pub fn q_literal<T: Debug>(&self, val: &T) -> String {
44        format!("> {:?}", val)
45    }
46
47    /// Returns a log line for an expression with string representation `expr`
48    /// and value `val`.
49    ///
50    /// ```
51    /// use q_debug::fmt::Formatter;
52    ///
53    /// let fmt = Formatter {};
54    ///
55    /// assert_eq!(
56    ///     fmt.q_expr(&3, &String::from("my_var")),
57    ///     String::from("> my_var = 3")
58    /// );
59    ///
60    /// assert_eq!(
61    ///     fmt.q_expr(&5, &String::from("2 + 3")),
62    ///     String::from("> 2 + 3 = 5")
63    /// );
64    /// ```
65    pub fn q_expr<T: Debug>(&self, val: &T, expr: &str) -> String {
66        format!("> {} = {:?}", expr, val)
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use std::thread;
74
75    macro_rules! ll {
76        ($filep: expr, $funcp:expr, $lineno: expr) => {
77            (
78                LogLocation {
79                    file_path: String::from($filep),
80                    func_path: String::from($funcp),
81                    lineno: $lineno,
82                    thread_id: thread::current().id(),
83                },
84                thread::current().id(),
85            )
86        };
87    }
88
89    #[test]
90    fn test_header() {
91        let formatter = Formatter {};
92        let (loc, tid) = ll!("src/lib.rs", "q_debug::tests::test_q", 42);
93
94        assert_eq!(
95            formatter.header(&Utc.ymd(2020, 6, 22).and_hms(20, 5, 32), &loc),
96            format!("[20:05:32 {:?} src/lib.rs q_debug::tests::test_q:42]", tid)
97        );
98    }
99
100    #[test]
101    fn test_q() {
102        let formatter = Formatter {};
103
104        assert_eq!(formatter.q(), ">");
105    }
106    //
107    #[test]
108    fn test_q_literal() {
109        let formatter = Formatter {};
110
111        assert_eq!(
112            formatter.q_literal(&String::from("Hello, world!")),
113            "> \"Hello, world!\""
114        );
115        assert_eq!(formatter.q_literal(&1), "> 1");
116    }
117
118    #[test]
119    fn test_q_expr() {
120        let formatter = Formatter {};
121
122        assert_eq!(
123            formatter.q_expr(&String::from("Hello, world!"), &String::from("my_var")),
124            "> my_var = \"Hello, world!\""
125        );
126        assert_eq!(
127            formatter.q_expr(&Some(42), &String::from("a_function(42)")),
128            "> a_function(42) = Some(42)"
129        );
130    }
131}