use std::{time::Duration, usize};
pub type LogStr = arraystring::SmallString;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum NumLog {
None,
S(&'static str),
I(i64),
F(f64),
Str(LogStr),
Dur(Duration),
Time(chrono::NaiveTime),
}
impl NumLog {
pub fn is_numeric(&self) -> bool {
match self {
NumLog::None => false,
NumLog::S(_) => false,
NumLog::I(_) => true,
NumLog::F(_) => true,
NumLog::Str(_) => false,
NumLog::Dur(_) => true,
NumLog::Time(_) => true,
}
}
}
impl Default for NumLog {
fn default() -> Self {
NumLog::None
}
}
impl std::fmt::Display for NumLog {
fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NumLog::None => write!(format, ""),
NumLog::S(s) => write!(format, "{s}"),
NumLog::I(i) => write!(format, "{i}"),
NumLog::F(f) => write!(format, "{f:.2}"),
NumLog::Str(s) => write!(format, "{s}"),
NumLog::Dur(s) => write!(format, "{s:?}"),
NumLog::Time(b) => write!(format, "{}", b.format("%H:%M:%S%.6f")),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct NumLogs<const L: usize> {
title: &'static str,
num_log: [NumLog; L],
index: usize,
}
impl<const L: usize> NumLogs<L> {
pub fn new(title: &'static str) -> Self {
let r = [Default::default(); L];
return Self {
title,
num_log: r,
index: 0,
};
}
pub fn get_title(&self) -> &'static str {
self.title
}
pub fn is_empty(&self) -> bool {
self.index == 0
}
pub fn len(&self) -> usize {
self.index
}
pub fn clear(&mut self) {
self.index = 0;
}
#[inline(always)]
pub fn add(&mut self, n: impl IntoNumLog) -> &mut Self {
let n = n.into_num_log();
if self.index >= L {
#[cfg(debug_assertions)]
eprintln!("NumLogs is full({} >= {}): {n}", self.index, L);
self.index += 1;
return self;
}
self.num_log[self.index] = n;
self.index += 1;
self
}
#[inline(always)]
pub fn push(&mut self, s: (&'static str, String)) -> &mut Self {
self.add(s.0).add(s.1)
}
#[inline(always)]
pub fn push_arr(&mut self, arr: Vec<(&'static str, String)>) -> &mut Self {
for ele in arr {
self.push(ele);
}
self
}
#[inline(always)]
pub fn add2(&mut self, n: impl IntoNumLog, n2: impl IntoNumLog) -> &mut Self {
self.add(n).add(n2)
}
#[inline(always)]
pub fn add_whitespace(&mut self) -> &mut Self {
self.add(", ")
}
#[inline(always)]
pub fn add_k(&mut self) -> &mut Self {
self.add(": ")
}
#[inline(always)]
pub fn add_arr<const ARR_LEN: usize, T: IntoNumLog>(
&mut self,
s_arr: [T; ARR_LEN],
) -> &mut Self {
for ele in s_arr {
let ele = ele.into_num_log();
self.add(ele);
}
self
}
#[inline(always)]
pub fn add_vec<T: IntoNumLog>(&mut self, s_arr: Vec<T>) -> &mut Self {
for ele in s_arr {
let ele = ele.into_num_log();
self.add(ele);
}
self
}
#[inline(always)]
pub fn append<const LEN: usize>(&mut self, vals: NumLogs<LEN>) -> &mut Self {
let mut i = vals.index;
for ele in vals.num_log {
self.add(ele);
i -= 1;
if i == 0 {
break;
}
}
self
}
}
pub trait IntoNumLog {
fn into_num_log(self) -> NumLog;
}
impl IntoNumLog for NumLog {
fn into_num_log(self) -> NumLog {
self
}
}
impl IntoNumLog for &'static str {
fn into_num_log(self) -> NumLog {
NumLog::S(self)
}
}
impl IntoNumLog for String {
fn into_num_log(self) -> NumLog {
NumLog::Str(self.as_str().into())
}
}
impl IntoNumLog for i32 {
fn into_num_log(self) -> NumLog {
NumLog::I(self as i64)
}
}
impl IntoNumLog for i64 {
fn into_num_log(self) -> NumLog {
NumLog::I(self)
}
}
impl IntoNumLog for usize {
fn into_num_log(self) -> NumLog {
NumLog::I(self as i64)
}
}
impl IntoNumLog for u32 {
fn into_num_log(self) -> NumLog {
NumLog::I(self as i64)
}
}
impl IntoNumLog for u64 {
fn into_num_log(self) -> NumLog {
NumLog::I(self as i64)
}
}
impl IntoNumLog for f32 {
fn into_num_log(self) -> NumLog {
NumLog::F(self as f64)
}
}
impl IntoNumLog for f64 {
fn into_num_log(self) -> NumLog {
NumLog::F(self)
}
}
impl IntoNumLog for Duration {
fn into_num_log(self) -> NumLog {
NumLog::Dur(self)
}
}
impl IntoNumLog for chrono::Duration {
fn into_num_log(self) -> NumLog {
NumLog::Dur(self.to_std().unwrap_or_else(|_| Duration::ZERO))
}
}
impl IntoNumLog for chrono::NaiveDateTime {
fn into_num_log(self) -> NumLog {
NumLog::Time(self.time())
}
}
impl IntoNumLog for chrono::NaiveDate {
fn into_num_log(self) -> NumLog {
self.format("%Y-%m-%d").to_string().into_num_log()
}
}
impl IntoNumLog for chrono::NaiveTime {
fn into_num_log(self) -> NumLog {
NumLog::Time(self)
}
}
impl<const L: usize> std::fmt::Display for NumLogs<L> {
fn fmt(&self, format: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
for i in 0..self.index {
if i == L {
break;
}
let v = &self.num_log[i];
s.push_str(&v.to_string());
if v.is_numeric() {
s.push_str(", ");
}
}
write!(format, "{}", s.trim_end_matches(", "))?;
Ok(())
}
}
pub trait NumTrait {
fn num(self) -> i64;
}
impl NumTrait for i64 {
fn num(self) -> i64 {
self
}
}
impl NumTrait for i128 {
fn num(self) -> i64 {
self as i64
}
}
impl NumTrait for i32 {
fn num(self) -> i64 {
self as i64
}
}
impl NumTrait for usize {
fn num(self) -> i64 {
self as i64
}
}
#[test]
fn test() {
let s = LogStr::from("123456789");
println!(
"num_logs 123456789 size_of_val: {}",
std::mem::size_of_val(&s)
);
println!("LogStr: {s}");
let s = LogStr::from("一二三四五六七八九");
println!(
"num_logs 一二三四五六七八九 size_of_val: {}",
std::mem::size_of_val(&s)
);
println!("LogStr: {s}");
let time = std::time::Instant::now();
let mut num_logs = NumLogs::<32>::new("test log");
println!("num_logs::new() elapsed: {:?}", time.elapsed());
println!("num_logs size_of_val: {}", std::mem::size_of_val(&num_logs));
num_logs
.add("is a ")
.add("string; ")
.add(1)
.add(2)
.add(3)
.add("floatVal: ")
.add(123.45678)
.add(2222.0)
.add("int64Val: ")
.add(3333_i64)
.add(4444_i32)
.add("字符串数组: ".to_string())
.add_arr([5555, 66666, 7777])
.add2("时间: ", chrono::Local::now().naive_local())
.add2("时间-date: ", chrono::Local::now().naive_local().date())
.add_whitespace()
.add2("时间-time: ", chrono::Local::now().naive_local().time())
.add_arr([5555, 66666, 7777])
.add2("耗时: ", time.elapsed())
.add(8888);
println!("num_logs: {}", num_logs);
let mut num_logs = NumLogs::<10>::new("test log: ");
for i in 1..=9 {
num_logs.add(i);
}
println!("num_logs<10>: {}", num_logs);
let mut num_logs = NumLogs::<10>::new("test log: ");
num_logs.add2("num1:", 1);
num_logs.add2("num2:", 2);
num_logs.add("num3");
println!("num_logs<5>: {}", num_logs);
let mut num_logs2 = NumLogs::<20>::new("test log: ");
for i in 1..=10 {
num_logs2.add(i);
}
num_logs2.append(num_logs);
num_logs2.add("; end");
println!("num_logs2: {}", num_logs2);
}