Skip to main content

wide_log/
key.rs

1/// Trait for wide-event keys.
2///
3/// Each variant of a key enum represents a JSON key in the wide event.
4/// The `wide_log!` macro generates the enum and this trait impl
5/// automatically from the JSON structure — users do not implement this
6/// trait manually.
7///
8/// # Path-Based Duration
9///
10/// [`DURATION_PATH`](Key::DURATION_PATH) specifies the nested path to the
11/// duration field (e.g. `[Duration, TotalMs]`). The guard auto-sets this
12/// field to the elapsed time in milliseconds on drop.
13///
14/// The user does **not** define `Log`, `Level`, or `Message` variants. Log
15/// entries are handled entirely internally by a `LogEntry` type and the
16/// `log_entries` field on [`WideEvent`].
17///
18/// [`WideEvent`]: crate::WideEvent
19pub trait Key: Copy + Eq + 'static {
20    /// Returns the JSON string representation of this key.
21    fn as_str(self) -> &'static str;
22
23    /// The total number of keys in the enum.
24    const MAX_KEYS: usize;
25
26    /// Returns the discriminant index of this key.
27    fn as_index(self) -> usize;
28
29    /// Path to the duration field (e.g. `[Duration, TotalMs]`).
30    /// Auto-set by the guard on drop. The value is in milliseconds (u64).
31    const DURATION_PATH: &'static [Self];
32}
33
34#[cfg(test)]
35pub(crate) mod test_support {
36    use super::Key;
37
38    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
39    #[repr(u8)]
40    pub enum TestKey {
41        Duration,
42        TotalMs,
43        Service,
44        Name,
45        Version,
46        Requests,
47        Status,
48        Details,
49        Tag,
50        Count,
51        Flag,
52    }
53
54    impl Key for TestKey {
55        fn as_str(self) -> &'static str {
56            match self {
57                TestKey::Duration => "duration",
58                TestKey::TotalMs => "total_ms",
59                TestKey::Service => "service",
60                TestKey::Name => "name",
61                TestKey::Version => "version",
62                TestKey::Requests => "requests",
63                TestKey::Status => "status",
64                TestKey::Details => "details",
65                TestKey::Tag => "tag",
66                TestKey::Count => "count",
67                TestKey::Flag => "flag",
68            }
69        }
70
71        const MAX_KEYS: usize = 11;
72
73        fn as_index(self) -> usize {
74            self as usize
75        }
76
77        const DURATION_PATH: &'static [Self] = &[TestKey::Duration, TestKey::TotalMs];
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84    use test_support::TestKey;
85
86    #[test]
87    fn key_as_str() {
88        assert_eq!(TestKey::Duration.as_str(), "duration");
89        assert_eq!(TestKey::TotalMs.as_str(), "total_ms");
90        assert_eq!(TestKey::Service.as_str(), "service");
91        assert_eq!(TestKey::Name.as_str(), "name");
92        assert_eq!(TestKey::Version.as_str(), "version");
93        assert_eq!(TestKey::Requests.as_str(), "requests");
94        assert_eq!(TestKey::Status.as_str(), "status");
95        assert_eq!(TestKey::Details.as_str(), "details");
96        assert_eq!(TestKey::Tag.as_str(), "tag");
97        assert_eq!(TestKey::Count.as_str(), "count");
98        assert_eq!(TestKey::Flag.as_str(), "flag");
99    }
100
101    #[test]
102    fn key_as_index() {
103        assert_eq!(TestKey::Duration.as_index(), 0);
104        assert_eq!(TestKey::TotalMs.as_index(), 1);
105        assert_eq!(TestKey::Service.as_index(), 2);
106        assert_eq!(TestKey::Name.as_index(), 3);
107        assert_eq!(TestKey::Version.as_index(), 4);
108        assert_eq!(TestKey::Requests.as_index(), 5);
109        assert_eq!(TestKey::Status.as_index(), 6);
110        assert_eq!(TestKey::Details.as_index(), 7);
111        assert_eq!(TestKey::Tag.as_index(), 8);
112        assert_eq!(TestKey::Count.as_index(), 9);
113        assert_eq!(TestKey::Flag.as_index(), 10);
114    }
115
116    #[test]
117    fn max_keys_correct() {
118        assert_eq!(TestKey::MAX_KEYS, 11);
119    }
120
121    #[test]
122    fn duration_path_correct() {
123        assert_eq!(
124            TestKey::DURATION_PATH,
125            &[TestKey::Duration, TestKey::TotalMs]
126        );
127    }
128}