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