use chrono::{DateTime, Local};
pub struct Epsilon;
impl Epsilon {
pub const FORMAT: f64 = 1e-9;
pub const COLOR: f32 = 1e-6;
}
#[must_use]
pub fn truncate_middle(s: &str, max_len: usize) -> String {
const ELLIPSIS: &str = "...";
let ellipsis_len = ELLIPSIS.chars().count();
if max_len <= ellipsis_len || s.chars().count() <= max_len {
return s.to_string();
}
let total_take = max_len - ellipsis_len;
let take_start = total_take / 2;
let take_end = total_take - take_start;
let start: String = s.chars().take(take_start).collect();
let n = s.chars().count();
let end: String = s.chars().skip(n.saturating_sub(take_end)).collect();
format!("{start}{ELLIPSIS}{end}")
}
#[must_use]
pub fn format_timestamp_ns(ns: i64) -> String {
const NS_PER_S: i64 = 1_000_000_000;
let secs = ns / NS_PER_S;
let subsec = ((ns % NS_PER_S) + NS_PER_S) % NS_PER_S;
match DateTime::from_timestamp(secs, subsec as u32) {
Some(utc) => {
let local = utc.with_timezone(&Local);
local.format("%Y-%m-%d %H:%M:%S").to_string()
}
None => format!("{ns} (invalid)"),
}
}
#[must_use]
pub fn clamp_selection(idx: usize, len: usize) -> usize {
idx.min(len.saturating_sub(1))
}
#[must_use]
pub fn clamp_selection_opt(idx: usize, len: usize) -> Option<usize> {
if len == 0 {
None
} else {
Some(clamp_selection(idx, len))
}
}
#[must_use]
pub fn frame_string_with_spaces(s: &str) -> String {
format!(" {s} ")
}
pub trait StringObjTraits {
fn new() -> Self
where
Self: Sized;
fn pad(&self, s: &str) -> String {
frame_string_with_spaces(s)
}
}