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 #[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 #[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}