use crate::types::AiLibError;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
pub fn save_temp_file(prefix: &str, bytes: &[u8]) -> io::Result<PathBuf> {
let mut dir = std::env::temp_dir();
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
let filename = format!("{}-{}.bin", prefix, ts);
dir.push(filename);
fs::write(&dir, bytes)?;
Ok(dir)
}
pub fn read_file(path: &Path) -> io::Result<Vec<u8>> {
fs::read(path)
}
pub fn remove_file(path: &Path) -> io::Result<()> {
fs::remove_file(path)
}
pub fn guess_mime_from_path(path: &Path) -> &'static str {
if let Some(ext) = path.extension().and_then(|s| s.to_str()) {
match ext.to_ascii_lowercase().as_str() {
"png" => "image/png",
"jpg" => "image/jpeg",
"jpeg" => "image/jpeg",
"gif" => "image/gif",
"webp" => "image/webp",
"mp3" => "audio/mpeg",
"wav" => "audio/wav",
"ogg" => "audio/ogg",
"mp4" => "video/mp4",
"avi" => "video/x-msvideo",
"mov" => "video/quicktime",
"pdf" => "application/pdf",
"txt" => "text/plain",
"md" => "text/markdown",
"json" => "application/json",
"xml" => "application/xml",
"html" => "text/html",
"css" => "text/css",
"js" => "application/javascript",
"zip" => "application/zip",
"tar" => "application/x-tar",
"gz" => "application/gzip",
_ => "application/octet-stream",
}
} else {
"application/octet-stream"
}
}
pub fn validate_file(path: &Path) -> Result<(), AiLibError> {
if !path.exists() {
return Err(AiLibError::FileError(format!(
"File does not exist: {}",
path.display()
)));
}
if !path.is_file() {
return Err(AiLibError::FileError(format!(
"Path is not a file: {}",
path.display()
)));
}
fs::metadata(path)
.map_err(|e| AiLibError::FileError(format!("Cannot read file metadata: {}", e)))?;
Ok(())
}
pub fn get_file_size(path: &Path) -> Result<u64, AiLibError> {
let metadata = fs::metadata(path)
.map_err(|e| AiLibError::FileError(format!("Cannot read file metadata: {}", e)))?;
Ok(metadata.len())
}
pub fn create_temp_dir(prefix: &str) -> io::Result<PathBuf> {
let mut dir = std::env::temp_dir();
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
let dirname = format!("{}-{}", prefix, ts);
dir.push(dirname);
fs::create_dir(&dir)?;
Ok(dir)
}
pub fn is_image_file(path: &Path) -> bool {
if let Some(ext) = path.extension().and_then(|s| s.to_str()) {
matches!(
ext.to_ascii_lowercase().as_str(),
"png" | "jpg" | "jpeg" | "gif" | "webp" | "bmp" | "tiff" | "svg"
)
} else {
false
}
}
pub fn is_audio_file(path: &Path) -> bool {
if let Some(ext) = path.extension().and_then(|s| s.to_str()) {
matches!(
ext.to_ascii_lowercase().as_str(),
"mp3" | "wav" | "ogg" | "flac" | "aac" | "m4a" | "wma"
)
} else {
false
}
}
pub fn is_video_file(path: &Path) -> bool {
if let Some(ext) = path.extension().and_then(|s| s.to_str()) {
matches!(
ext.to_ascii_lowercase().as_str(),
"mp4" | "avi" | "mov" | "wmv" | "flv" | "mkv" | "webm" | "m4v"
)
} else {
false
}
}
pub fn is_text_file(path: &Path) -> bool {
if let Some(ext) = path.extension().and_then(|s| s.to_str()) {
matches!(
ext.to_ascii_lowercase().as_str(),
"txt"
| "md"
| "json"
| "xml"
| "html"
| "css"
| "js"
| "rs"
| "py"
| "java"
| "cpp"
| "c"
)
} else {
false
}
}
pub fn get_file_extension(path: &Path) -> Option<String> {
path.extension()
.and_then(|s| s.to_str())
.map(|s| s.to_ascii_lowercase())
}
pub fn is_file_size_acceptable(path: &Path, max_size_mb: u64) -> Result<bool, AiLibError> {
let size = get_file_size(path)?;
let max_size_bytes = max_size_mb * 1024 * 1024;
Ok(size <= max_size_bytes)
}