macula_rust/frame/
wire_counters.rs1use std::collections::HashMap;
6use std::sync::{LazyLock, Mutex, MutexGuard};
7
8#[derive(Debug, Clone, Default, PartialEq, Eq)]
10pub struct WireCounts {
11 pub unknown_frame_type: u64,
14 pub ext_ignored: HashMap<String, u64>,
17 pub ext_refused: HashMap<String, u64>,
20 pub enum_fallback: HashMap<String, u64>,
23}
24
25static COUNTS: LazyLock<Mutex<WireCounts>> = LazyLock::new(Mutex::default);
26
27fn counts() -> MutexGuard<'static, WireCounts> {
28 COUNTS
29 .lock()
30 .unwrap_or_else(|poisoned| poisoned.into_inner())
31}
32
33pub fn wire_counters() -> WireCounts {
35 counts().clone()
36}
37
38pub(crate) fn count_unknown_frame_type() {
40 counts().unknown_frame_type += 1;
41}
42
43pub const MAX_COUNTED_NAMES: usize = 64;
46
47pub const OTHER: &str = "other";
49
50pub(crate) fn count_ext_ignored(name: &str) {
53 count_named(&mut counts().ext_ignored, name);
54}
55
56pub(crate) fn count_ext_refused(name: &str) {
58 count_named(&mut counts().ext_refused, name);
59}
60
61fn count_named(by_name: &mut HashMap<String, u64>, name: &str) {
64 let label = match by_name.contains_key(name) || by_name.len() < MAX_COUNTED_NAMES {
65 true => name,
66 false => OTHER,
67 };
68 *by_name.entry(label.to_owned()).or_default() += 1;
69}
70
71pub(crate) fn count_enum_fallback(field: &str) {
73 *counts().enum_fallback.entry(field.to_owned()).or_default() += 1;
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn a_counter_keeps_64_names_apart_and_the_rest_under_other() {
82 let mut by_name = HashMap::new();
83 for n in 0..MAX_COUNTED_NAMES + 10 {
84 count_named(&mut by_name, &format!("example.e{n}"));
85 }
86 count_named(&mut by_name, "example.e0");
87 assert_eq!(by_name.len(), MAX_COUNTED_NAMES + 1);
88 assert_eq!(by_name[OTHER], 10);
89 assert_eq!(
90 by_name["example.e0"], 2,
91 "a name already kept is counted as itself"
92 );
93 }
94}