use std::time::{SystemTime, UNIX_EPOCH};
pub fn generate_timestamp_id() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as u64
}
pub fn format_bytes(bytes: u64) -> String {
const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB", "PB"];
if bytes == 0 {
return "0 B".to_string();
}
let bytes_f64 = bytes as f64;
let exp = (bytes_f64.log2() / 10.0).floor() as usize;
let unit_index = exp.min(UNITS.len() - 1);
let size = bytes_f64 / (1024_f64).powi(unit_index as i32);
if size >= 100.0 {
format!("{:.0} {}", size, UNITS[unit_index])
} else if size >= 10.0 {
format!("{:.1} {}", size, UNITS[unit_index])
} else {
format!("{:.2} {}", size, UNITS[unit_index])
}
}
pub fn clamp<T: PartialOrd>(value: T, min: T, max: T) -> T {
if value < min {
min
} else if value > max {
max
} else {
value
}
}
pub fn next_power_of_two(n: u64) -> u64 {
if n <= 1 {
1
} else {
n.next_power_of_two()
}
}
pub fn is_power_of_two(n: u64) -> bool {
n != 0 && (n & (n - 1)) == 0
}
pub fn align_to(value: u64, alignment: u64) -> u64 {
(value + alignment - 1) / alignment * alignment
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_bytes() {
assert_eq!(format_bytes(0), "0 B");
assert_eq!(format_bytes(1023), "1023 B");
assert_eq!(format_bytes(1024), "1.00 KB");
assert_eq!(format_bytes(1536), "1.50 KB");
assert_eq!(format_bytes(1048576), "1.00 MB");
assert_eq!(format_bytes(1073741824), "1.00 GB");
}
#[test]
fn test_power_of_two() {
assert_eq!(next_power_of_two(0), 1);
assert_eq!(next_power_of_two(1), 1);
assert_eq!(next_power_of_two(2), 2);
assert_eq!(next_power_of_two(3), 4);
assert_eq!(next_power_of_two(5), 8);
assert!(is_power_of_two(1));
assert!(is_power_of_two(2));
assert!(is_power_of_two(4));
assert!(!is_power_of_two(3));
assert!(!is_power_of_two(0));
}
#[test]
fn test_align() {
assert_eq!(align_to(0, 8), 0);
assert_eq!(align_to(1, 8), 8);
assert_eq!(align_to(7, 8), 8);
assert_eq!(align_to(8, 8), 8);
assert_eq!(align_to(9, 8), 16);
}
}