1use std::{time::Duration, usize};
2
3pub type LogStr = arraystring::SmallString;
4
5#[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 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#[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 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 #[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 #[cfg(debug_assertions)]
100 eprintln!("NumLogs is full '{}', ({} >= {}): last content: {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 #[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}