use async_trait::async_trait;
use tokio::fs;
use super::parser::OpenApiParser;
use crate::generation::{GenerationError, OpenApiContext, OpenApiLoader};
pub struct FileOpenApiLoader;
impl FileOpenApiLoader {
pub fn new() -> Self {
Self
}
}
#[async_trait]
impl OpenApiLoader for FileOpenApiLoader {
async fn load(&self, source: &str) -> Result<OpenApiContext, GenerationError> {
tracing::debug!("FileOpenApiLoader: Attempting to load from path: {source}");
let content = fs::read_to_string(source).await.map_err(|e| {
tracing::error!("FileOpenApiLoader: Failed to read file '{source}': {e}");
GenerationError::IoError(e)
})?;
let spec_value = if source.ends_with(".json") {
serde_json::from_str(&content).map_err(GenerationError::SerializationError)?
} else if source.ends_with(".yaml") || source.ends_with(".yml") {
serde_yaml::from_str(&content)
.map_err(|e| GenerationError::LoadError(format!("Failed to parse YAML: {e}")))?
} else {
serde_json::from_str(&content)
.or_else(|_| serde_yaml::from_str(&content))
.map_err(|e| {
GenerationError::LoadError(format!("Failed to parse OpenAPI spec: {e}"))
})?
};
let parser = OpenApiParser::new(spec_value);
parser.parse().await
}
}
impl Default for FileOpenApiLoader {
fn default() -> Self {
Self::new()
}
}