use chrono::Duration;
use std::path::Path;
use uuid::Uuid;
pub fn generate_id() -> String {
Uuid::new_v4().to_string()
}
pub fn format_duration(seconds: f64) -> String {
let duration = Duration::seconds(seconds as i64);
let hours = duration.num_hours();
let minutes = duration.num_minutes() % 60;
let secs = duration.num_seconds() % 60;
let millis = duration.num_milliseconds() % 1000;
if hours > 0 {
format!("{}h {}m {}.{}s", hours, minutes, secs, millis)
} else if minutes > 0 {
format!("{}m {}.{}s", minutes, secs, millis)
} else {
format!("{}.{}s", secs, millis)
}
}
pub fn format_file_size(bytes: u64) -> String {
let units = ["B", "KB", "MB", "GB", "TB"];
let mut size = bytes as f64;
let mut unit_index = 0;
while size >= 1024.0 && unit_index < units.len() - 1 {
size /= 1024.0;
unit_index += 1;
}
format!("{:.2} {}", size, units[unit_index])
}
pub fn get_file_extension(path: &Path) -> Option<String> {
path.extension()
.and_then(|ext| ext.to_str())
.map(|ext| ext.to_lowercase())
}
pub fn is_video_file(path: &Path) -> bool {
const VIDEO_EXTENSIONS: &[&str] = &["mp4", "webm", "avi", "mov", "mkv", "flv", "wmv", "m4v"];
if let Some(ext) = get_file_extension(path) {
VIDEO_EXTENSIONS.contains(&ext.as_str())
} else {
false
}
}
pub fn is_audio_file(path: &Path) -> bool {
const AUDIO_EXTENSIONS: &[&str] = &["mp3", "wav", "ogg", "flac", "aac", "wma", "m4a"];
if let Some(ext) = get_file_extension(path) {
AUDIO_EXTENSIONS.contains(&ext.as_str())
} else {
false
}
}
pub fn truncate_string(s: &str, max_len: usize) -> String {
if s.len() <= max_len {
s.to_string()
} else {
format!("{}{}", &s[..max_len - 3], "...")
}
}
pub fn is_valid_uuid(uuid: &str) -> bool {
Uuid::parse_str(uuid).is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn test_generate_id() {
let id1 = generate_id();
let id2 = generate_id();
assert_ne!(id1, id2);
assert_eq!(id1.len(), 36); }
#[test]
fn test_format_duration() {
assert_eq!(format_duration(60.0), "1m 0.0s");
assert_eq!(format_duration(3600.0), "1h 0m 0.0s");
assert_eq!(format_duration(3661.5), "1h 1m 1.0s");
assert_eq!(format_duration(0.0), "0.0s");
}
#[test]
fn test_format_file_size() {
assert_eq!(format_file_size(1024), "1.00 KB");
assert_eq!(format_file_size(1024 * 1024), "1.00 MB");
assert_eq!(format_file_size(500), "500.00 B");
}
#[test]
fn test_get_file_extension() {
let path = Path::new("video.mp4");
assert_eq!(get_file_extension(path), Some("mp4".to_string()));
let path = Path::new("audio.MP3");
assert_eq!(get_file_extension(path), Some("mp3".to_string()));
let path = Path::new("file");
assert_eq!(get_file_extension(path), None);
}
#[test]
fn test_is_video_file() {
let video_path = Path::new("video.mp4");
let audio_path = Path::new("audio.mp3");
let text_path = Path::new("text.txt");
assert!(is_video_file(video_path));
assert!(!is_video_file(audio_path));
assert!(!is_video_file(text_path));
}
#[test]
fn test_is_audio_file() {
let audio_path = Path::new("audio.mp3");
let video_path = Path::new("video.mp4");
let text_path = Path::new("text.txt");
assert!(is_audio_file(audio_path));
assert!(!is_audio_file(video_path));
assert!(!is_audio_file(text_path));
}
#[test]
fn test_truncate_string() {
let long_str = "This is a very long string that needs to be truncated";
assert_eq!(truncate_string(long_str, 20), "This is a very lo...");
assert_eq!(truncate_string(long_str, 100), long_str);
}
#[test]
fn test_is_valid_uuid() {
let valid_uuid = "123e4567-e89b-12d3-a456-426614174000";
let invalid_uuid = "invalid-uuid";
assert!(is_valid_uuid(valid_uuid));
assert!(!is_valid_uuid(invalid_uuid));
}
}