fast_able/
num_log.rs

1use std::{time::Duration, usize};
2
3pub type LogStr = arraystring::SmallString;
4
5/// Enum representing different types of log values
6/// 表示不同类型日志值的枚举
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub enum NumLog {
9    None,
10    S(&'static str),
11    I(i64),
12    F(f64),
13    Str(LogStr),
14    Dur(Duration),
15    Time(chrono::NaiveTime),
16}
17
18impl NumLog {
19    /// Check if the log value is numeric
20    /// 检查日志值是否为数字
21    pub fn is_numeric(&self) -> bool {
22        match self {
23            NumLog::None => false,
24            NumLog::S(_) => false,
25            NumLog::I(_) => true,
26            NumLog::F(_) => true,
27            NumLog::Str(_) => false,
28            NumLog::Dur(_) => true,
29            NumLog::Time(_) => true,
30        }
31    }
32}
33
34impl Default for NumLog {
35    fn default() -> Self {
36        NumLog::None
37    }
38}
39
40impl std::fmt::Display for NumLog {
41    fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        match self {
43            NumLog::None => write!(format, ""),
44            NumLog::S(s) => write!(format, "{s}"),
45            NumLog::I(i) => write!(format, "{i}"),
46            NumLog::F(f) => write!(format, "{f:.2}"),
47            NumLog::Str(s) => write!(format, "{s}"),
48            NumLog::Dur(s) => write!(format, "{s:?}"),
49            NumLog::Time(b) => write!(format, "{}", b.format("%H:%M:%S%.6f")),
50        }
51    }
52}
53
54/// Struct to hold a fixed number of log entries
55/// 保存固定数量日志条目的结构体
56#[derive(Debug, Clone, Copy)]
57pub struct NumLogs<const L: usize> {
58    title: &'static str,
59    num_log: [NumLog; L],
60    index: usize,
61}
62
63impl<const L: usize> NumLogs<L> {
64    /// Create a new NumLogs instance
65    /// 创建一个新的 NumLogs 实例
66    pub fn new(title: &'static str) -> Self {
67        let r = [Default::default(); L];
68        return Self {
69            title,
70            num_log: r,
71            index: 0,
72        };
73    }
74
75    pub fn get_title(&self) -> &'static str {
76        self.title
77    }
78
79    pub fn is_empty(&self) -> bool {
80        self.index == 0
81    }
82
83    pub fn len(&self) -> usize {
84        self.index
85    }
86
87    pub fn clear(&mut self) {
88        self.index = 0;
89    }
90
91    /// Add a log entry
92    /// 添加一个日志条目
93    #[inline(always)]
94    pub fn add(&mut self, n: impl IntoNumLog) -> &mut Self {
95        let n = n.into_num_log();
96        if self.index >= L {
97            #[cfg(debug_assertions)]
98            eprintln!("NumLogs is full({} >= {}): {n}", self.index, L);
99
100            self.index += 1;
101            return self;
102        }
103        self.num_log[self.index] = n;
104        self.index += 1;
105        self
106    }
107
108    /// Push a key-value pair log entry
109    /// 推送一个键值对日志条目
110    #[inline(always)]
111    pub fn push(&mut self, s: (&'static str, String)) -> &mut Self {
112        self.add(s.0).add(s.1)
113    }
114
115    #[inline(always)]
116    pub fn push_arr(&mut self, arr: Vec<(&'static str, String)>) -> &mut Self {
117        for ele in arr {
118            self.push(ele);
119        }
120        self
121    }
122
123    #[inline(always)]
124    pub fn add2(&mut self, n: impl IntoNumLog, n2: impl IntoNumLog) -> &mut Self {
125        self.add(n).add(n2)
126    }
127
128    #[inline(always)]
129    pub fn add_whitespace(&mut self) -> &mut Self {
130        self.add(", ")
131    }
132
133    #[inline(always)]
134    pub fn add_k(&mut self) -> &mut Self {
135        self.add(": ")
136    }
137
138    #[inline(always)]
139    pub fn add_arr<const ARR_LEN: usize, T: IntoNumLog>(
140        &mut self,
141        s_arr: [T; ARR_LEN],
142    ) -> &mut Self {
143        for ele in s_arr {
144            let ele = ele.into_num_log();
145            self.add(ele);
146        }
147        self
148    }
149
150    #[inline(always)]
151    pub fn add_vec<T: IntoNumLog>(&mut self, s_arr: Vec<T>) -> &mut Self {
152        for ele in s_arr {
153            let ele = ele.into_num_log();
154            self.add(ele);
155        }
156        self
157    }
158
159    #[inline(always)]
160    pub fn append<const LEN: usize>(&mut self, vals: NumLogs<LEN>) -> &mut Self {
161        let mut i = vals.index;
162        for ele in vals.num_log {
163            self.add(ele);
164            i -= 1;
165            if i == 0 {
166                break;
167            }
168        }
169        self
170    }
171}
172
173pub trait IntoNumLog {
174    fn into_num_log(self) -> NumLog;
175}
176
177impl IntoNumLog for NumLog {
178    fn into_num_log(self) -> NumLog {
179        self
180    }
181}
182
183impl IntoNumLog for &'static str {
184    fn into_num_log(self) -> NumLog {
185        NumLog::S(self)
186    }
187}
188
189impl IntoNumLog for String {
190    fn into_num_log(self) -> NumLog {
191        NumLog::Str(self.as_str().into())
192    }
193}
194
195impl IntoNumLog for i32 {
196    fn into_num_log(self) -> NumLog {
197        NumLog::I(self as i64)
198    }
199}
200
201impl IntoNumLog for i64 {
202    fn into_num_log(self) -> NumLog {
203        NumLog::I(self)
204    }
205}
206
207impl IntoNumLog for usize {
208    fn into_num_log(self) -> NumLog {
209        NumLog::I(self as i64)
210    }
211}
212
213impl IntoNumLog for u32 {
214    fn into_num_log(self) -> NumLog {
215        NumLog::I(self as i64)
216    }
217}
218
219impl IntoNumLog for u64 {
220    fn into_num_log(self) -> NumLog {
221        NumLog::I(self as i64)
222    }
223}
224
225impl IntoNumLog for f32 {
226    fn into_num_log(self) -> NumLog {
227        NumLog::F(self as f64)
228    }
229}
230
231impl IntoNumLog for f64 {
232    fn into_num_log(self) -> NumLog {
233        NumLog::F(self)
234    }
235}
236
237impl IntoNumLog for Duration {
238    fn into_num_log(self) -> NumLog {
239        NumLog::Dur(self)
240    }
241}
242
243impl IntoNumLog for chrono::Duration {
244    fn into_num_log(self) -> NumLog {
245        NumLog::Dur(self.to_std().unwrap_or_else(|_| Duration::ZERO))
246    }
247}
248
249impl IntoNumLog for chrono::NaiveDateTime {
250    fn into_num_log(self) -> NumLog {
251        NumLog::Time(self.time())
252    }
253}
254
255impl IntoNumLog for chrono::NaiveDate {
256    fn into_num_log(self) -> NumLog {
257        self.format("%Y-%m-%d").to_string().into_num_log()
258    }
259}
260
261impl IntoNumLog for chrono::NaiveTime {
262    fn into_num_log(self) -> NumLog {
263        NumLog::Time(self)
264    }
265}
266
267impl<const L: usize> std::fmt::Display for NumLogs<L> {
268    fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269        let mut s = String::new();
270        for i in 0..self.index {
271            if i == L {
272                break;
273            }
274            let v = &self.num_log[i];
275            s.push_str(&v.to_string());
276            if v.is_numeric() {
277                s.push_str(", ");
278            }
279        }
280        write!(format, "{}", s.trim_end_matches(", "))?;
281        Ok(())
282    }
283}
284
285pub trait NumTrait {
286    fn num(self) -> i64;
287}
288
289impl NumTrait for i64 {
290    fn num(self) -> i64 {
291        self
292    }
293}
294
295impl NumTrait for i128 {
296    fn num(self) -> i64 {
297        self as i64
298    }
299}
300
301impl NumTrait for i32 {
302    fn num(self) -> i64 {
303        self as i64
304    }
305}
306
307impl NumTrait for usize {
308    fn num(self) -> i64 {
309        self as i64
310    }
311}
312
313#[test]
314fn test() {
315    let s = LogStr::from("123456789");
316    println!(
317        "num_logs 123456789 size_of_val: {}",
318        std::mem::size_of_val(&s)
319    );
320    println!("LogStr: {s}");
321
322    let s = LogStr::from("一二三四五六七八九");
323    println!(
324        "num_logs 一二三四五六七八九 size_of_val: {}",
325        std::mem::size_of_val(&s)
326    );
327    println!("LogStr: {s}");
328
329    let time = std::time::Instant::now();
330    let mut num_logs = NumLogs::<32>::new("test log");
331    println!("num_logs::new() elapsed: {:?}", time.elapsed());
332
333    println!("num_logs size_of_val: {}", std::mem::size_of_val(&num_logs));
334    num_logs
335        .add("is a ")
336        .add("string; ")
337        .add(1)
338        .add(2)
339        .add(3)
340        .add("floatVal: ")
341        .add(123.45678)
342        .add(2222.0)
343        .add("int64Val: ")
344        .add(3333_i64)
345        .add(4444_i32)
346        .add("字符串数组: ".to_string())
347        .add_arr([5555, 66666, 7777])
348        .add2("时间: ", chrono::Local::now().naive_local())
349        .add2("时间-date: ", chrono::Local::now().naive_local().date())
350        .add_whitespace()
351        .add2("时间-time: ", chrono::Local::now().naive_local().time())
352        .add_arr([5555, 66666, 7777])
353        .add2("耗时: ", time.elapsed())
354        .add(8888);
355    println!("num_logs: {}", num_logs);
356
357    let mut num_logs = NumLogs::<10>::new("test log: ");
358    for i in 1..=9 {
359        num_logs.add(i);
360    }
361    println!("num_logs<10>: {}", num_logs);
362
363    let mut num_logs = NumLogs::<10>::new("test log: ");
364    num_logs.add2("num1:", 1);
365    num_logs.add2("num2:", 2);
366    num_logs.add("num3");
367    println!("num_logs<5>: {}", num_logs);
368
369    let mut num_logs2 = NumLogs::<20>::new("test log: ");
370    for i in 1..=10 {
371        num_logs2.add(i);
372    }
373    num_logs2.append(num_logs);
374    num_logs2.add("; end");
375    println!("num_logs2: {}", num_logs2);
376}