use bincode::{Decode, Encode};
use cu29_clock::CuTime;
use cu29_traits::{CuError, CuResult};
pub use cu29_value as value;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Display;
use std::path::{Path, PathBuf};
use strfmt::strfmt;
use value::Value;
const INDEX_DIR_NAME: &str = "cu29_log_index";
#[allow(dead_code)]
pub const ANONYMOUS: u32 = 0;
#[derive(Debug, Encode, Decode, Serialize, Deserialize, PartialEq)]
pub struct CuLogEntry {
pub time: CuTime,
pub msg_index: u32,
pub paramname_indexes: Vec<u32>,
pub params: Vec<Value>,
}
impl Display for CuLogEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"CuLogEntry {{ msg_index: {}, paramname_indexes: {:?}, params: {:?} }}",
self.msg_index, self.paramname_indexes, self.params
)
}
}
impl CuLogEntry {
pub fn new(msg_index: u32) -> Self {
CuLogEntry {
time: 0.into(), msg_index,
paramname_indexes: Vec::new(),
params: Vec::new(),
}
}
pub fn add_param(&mut self, paramname_index: u32, param: Value) {
self.paramname_indexes.push(paramname_index);
self.params.push(param);
}
}
pub fn rebuild_logline(all_interned_strings: &Vec<String>, entry: &CuLogEntry) -> CuResult<String> {
let mut format_string = all_interned_strings[entry.msg_index as usize].clone();
let mut vars = HashMap::new();
for (i, param) in entry.params.iter().enumerate() {
let param_as_string = format!("{}", param);
if entry.paramname_indexes[i] == 0 {
format_string = format_string.replacen("{}", ¶m_as_string, 1);
} else {
let name = all_interned_strings[entry.paramname_indexes[i] as usize].clone();
vars.insert(name, param_as_string);
}
}
if vars.is_empty() {
return Ok(format_string);
}
strfmt(&format_string, &vars).map_err(|e| {
CuError::new_with_cause(
format!(
"Failed to format log line: {:?} with variables [{:?}]",
format_string, vars
)
.as_str(),
e,
)
})
}
fn parent_n_times(path: &Path, n: usize) -> Option<PathBuf> {
let mut result = Some(path.to_path_buf());
for _ in 0..n {
result = result?.parent().map(PathBuf::from);
}
result
}
pub fn default_log_index_dir() -> PathBuf {
let outdir = std::env::var("OUT_DIR").expect("no OUT_DIR set, build.rs must be broken");
let outdir_path = Path::new(&outdir);
let target_dir = parent_n_times(&outdir_path, 3)
.unwrap()
.join(INDEX_DIR_NAME);
target_dir
}