use std::collections::HashMap;
use std::fs;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum FileCategory {
None,
Readme,
Apis,
Models,
ProjectFiles,
Runtime,
}
#[derive(Debug, Clone)]
pub struct FileInfo {
pub filename: String,
pub content: String,
pub category: FileCategory,
}
impl FileInfo {
pub fn new(filename: String, content: String, category: FileCategory) -> Self {
Self {
filename,
content,
category,
}
}
pub fn none(filename: String, content: String) -> Self {
Self::new(filename, content, FileCategory::None)
}
pub fn readme(filename: String, content: String) -> Self {
Self::new(filename, content, FileCategory::Readme)
}
pub fn api(filename: String, content: String) -> Self {
Self::new(filename, content, FileCategory::Apis)
}
pub fn model(filename: String, content: String) -> Self {
Self::new(filename, content, FileCategory::Models)
}
pub fn project(filename: String, content: String) -> Self {
Self::new(filename, content, FileCategory::ProjectFiles)
}
pub fn runtime(filename: String, content: String) -> Self {
Self::new(filename, content, FileCategory::Runtime)
}
}
pub trait FileWriter {
fn source_dir(&self) -> Option<&str> {
None
}
fn write_files(
&self,
output_dir: &std::path::Path,
files: &[FileInfo],
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut files_by_category: HashMap<FileCategory, Vec<&FileInfo>> = HashMap::new();
for file in files {
files_by_category
.entry(file.category.clone())
.or_default()
.push(file);
}
let source_root = self
.source_dir()
.map(|d| output_dir.join(d))
.unwrap_or_else(|| output_dir.to_path_buf());
for (category, category_files) in files_by_category {
let category_dir = match category {
FileCategory::None => continue,
FileCategory::Readme => output_dir.to_path_buf(),
FileCategory::Apis => source_root.join("apis"),
FileCategory::Models => source_root.join("models"),
FileCategory::ProjectFiles => output_dir.to_path_buf(),
FileCategory::Runtime => source_root.join("runtime"),
};
if !category_dir.exists() {
fs::create_dir_all(&category_dir)?;
}
for file in category_files {
let file_path = category_dir.join(&file.filename);
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent)?;
}
fs::write(&file_path, &file.content)?;
}
}
Ok(())
}
}