Skip to main content

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
98            // 日志满了
99            #[cfg(debug_assertions)]
100            eprintln!("NumLogs is full '{}', ({} >= {}): len: {n}", self.title, self.index, L);
101
102            self.index += 1;
103            return self;
104        }
105        self.num_log[self.index] = n;
106        self.index += 1;
107        self
108    }
109
110    /// Push a key-value pair log entry
111    /// 推送一个键值对日志条目
112    #[inline(always)]
113    pub fn push(&mut self, s: (&'static str, String)) -> &mut Self {
114        self.add(s.0).add(s.1)
115    }
116
117    #[inline(always)]
118    pub fn push_arr(&mut self, arr: Vec<(&'static str, String)>) -> &mut Self {
119        for ele in arr {
120            self.push(ele);
121        }
122        self
123    }
124
125    #[inline(always)]
126    pub fn add2(&mut self, n: impl IntoNumLog, n2: impl IntoNumLog) -> &mut Self {
127        self.add(n).add(n2)
128    }
129
130    #[inline(always)]
131    pub fn add_whitespace(&mut self) -> &mut Self {
132        self.add(", ")
133    }
134
135    #[inline(always)]
136    pub fn add_k(&mut self) -> &mut Self {
137        self.add(": ")
138    }
139
140    #[inline(always)]
141    pub fn add_arr<const ARR_LEN: usize, T: IntoNumLog>(
142        &mut self,
143        s_arr: [T; ARR_LEN],
144    ) -> &mut Self {
145        for ele in s_arr {
146            let ele = ele.into_num_log();
147            self.add(ele);
148        }
149        self
150    }
151
152    #[inline(always)]
153    pub fn add_vec<T: IntoNumLog>(&mut self, s_arr: Vec<T>) -> &mut Self {
154        for ele in s_arr {
155            let ele = ele.into_num_log();
156            self.add(ele);
157        }
158        self
159    }
160
161    #[inline(always)]
162    pub fn append<const LEN: usize>(&mut self, vals: NumLogs<LEN>) -> &mut Self {
163        let mut i = vals.index;
164        for ele in vals.num_log {
165            self.add(ele);
166            i -= 1;
167            if i == 0 {
168                break;
169            }
170        }
171        self
172    }
173}
174
175pub trait IntoNumLog {
176    fn into_num_log(self) -> NumLog;
177}
178
179impl IntoNumLog for NumLog {
180    fn into_num_log(self) -> NumLog {
181        self
182    }
183}
184
185impl IntoNumLog for &'static str {
186    fn into_num_log(self) -> NumLog {
187        NumLog::S(self)
188    }
189}
190
191impl IntoNumLog for String {
192    fn into_num_log(self) -> NumLog {
193        NumLog::Str(self.as_str().into())
194    }
195}
196
197impl IntoNumLog for i32 {
198    fn into_num_log(self) -> NumLog {
199        NumLog::I(self as i64)
200    }
201}
202
203impl IntoNumLog for i64 {
204    fn into_num_log(self) -> NumLog {
205        NumLog::I(self)
206    }
207}
208
209impl IntoNumLog for usize {
210    fn into_num_log(self) -> NumLog {
211        NumLog::I(self as i64)
212    }
213}
214
215impl IntoNumLog for u32 {
216    fn into_num_log(self) -> NumLog {
217        NumLog::I(self as i64)
218    }
219}
220
221impl IntoNumLog for u64 {
222    fn into_num_log(self) -> NumLog {
223        NumLog::I(self as i64)
224    }
225}
226
227impl IntoNumLog for f32 {
228    fn into_num_log(self) -> NumLog {
229        NumLog::F(self as f64)
230    }
231}
232
233impl IntoNumLog for f64 {
234    fn into_num_log(self) -> NumLog {
235        NumLog::F(self)
236    }
237}
238
239impl IntoNumLog for Duration {
240    fn into_num_log(self) -> NumLog {
241        NumLog::Dur(self)
242    }
243}
244
245impl IntoNumLog for chrono::Duration {
246    fn into_num_log(self) -> NumLog {
247        NumLog::Dur(self.to_std().unwrap_or_else(|_| Duration::ZERO))
248    }
249}
250
251impl IntoNumLog for chrono::NaiveDateTime {
252    fn into_num_log(self) -> NumLog {
253        NumLog::Time(self.time())
254    }
255}
256
257impl IntoNumLog for chrono::NaiveDate {
258    fn into_num_log(self) -> NumLog {
259        self.format("%Y-%m-%d").to_string().into_num_log()
260    }
261}
262
263impl IntoNumLog for chrono::NaiveTime {
264    fn into_num_log(self) -> NumLog {
265        NumLog::Time(self)
266    }
267}
268
269impl<const L: usize> std::fmt::Display for NumLogs<L> {
270    fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271        let mut s = String::new();
272        for i in 0..self.index {
273            if i == L {
274                break;
275            }
276            let v = &self.num_log[i];
277            s.push_str(&v.to_string());
278            if v.is_numeric() {
279                s.push_str(", ");
280            }
281        }
282        write!(format, "{}", s.trim_end_matches(", "))?;
283        Ok(())
284    }
285}
286
287pub trait NumTrait {
288    fn num(self) -> i64;
289}
290
291impl NumTrait for i64 {
292    fn num(self) -> i64 {
293        self
294    }
295}
296
297impl NumTrait for i128 {
298    fn num(self) -> i64 {
299        self as i64
300    }
301}
302
303impl NumTrait for i32 {
304    fn num(self) -> i64 {
305        self as i64
306    }
307}
308
309impl NumTrait for usize {
310    fn num(self) -> i64 {
311        self as i64
312    }
313}
314
315#[test]
316fn test() {
317    let s = LogStr::from("123456789");
318    println!(
319        "num_logs 123456789 size_of_val: {}",
320        std::mem::size_of_val(&s)
321    );
322    println!("LogStr: {s}");
323
324    let s = LogStr::from("一二三四五六七八九");
325    println!(
326        "num_logs 一二三四五六七八九 size_of_val: {}",
327        std::mem::size_of_val(&s)
328    );
329    println!("LogStr: {s}");
330
331    let time = std::time::Instant::now();
332    let mut num_logs = NumLogs::<32>::new("test log");
333    println!("num_logs::new() elapsed: {:?}", time.elapsed());
334
335    println!("num_logs size_of_val: {}", std::mem::size_of_val(&num_logs));
336    num_logs
337        .add("is a ")
338        .add("string; ")
339        .add(1)
340        .add(2)
341        .add(3)
342        .add("floatVal: ")
343        .add(123.45678)
344        .add(2222.0)
345        .add("int64Val: ")
346        .add(3333_i64)
347        .add(4444_i32)
348        .add("字符串数组: ".to_string())
349        .add_arr([5555, 66666, 7777])
350        .add2("时间: ", chrono::Local::now().naive_local())
351        .add2("时间-date: ", chrono::Local::now().naive_local().date())
352        .add_whitespace()
353        .add2("时间-time: ", chrono::Local::now().naive_local().time())
354        .add_arr([5555, 66666, 7777])
355        .add2("耗时: ", time.elapsed())
356        .add(8888);
357    println!("num_logs: {}", num_logs);
358
359    let mut num_logs = NumLogs::<10>::new("test log: ");
360    for i in 1..=9 {
361        num_logs.add(i);
362    }
363    println!("num_logs<10>: {}", num_logs);
364
365    let mut num_logs = NumLogs::<10>::new("test log: ");
366    num_logs.add2("num1:", 1);
367    num_logs.add2("num2:", 2);
368    num_logs.add("num3");
369    println!("num_logs<5>: {}", num_logs);
370
371    let mut num_logs2 = NumLogs::<20>::new("test log: ");
372    for i in 1..=10 {
373        num_logs2.add(i);
374    }
375    num_logs2.append(num_logs);
376    num_logs2.add("; end");
377    println!("num_logs2: {}", num_logs2);
378}