use std::{ffi::CString, path::Path};
use cloudcover_core::{GoMethodReference, SdkModule};
use crate::{
GoAnalysisError,
ffi::{AnalyzerResponseGuard, analyze_go},
response::AnalyzerResponse,
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GoAnalysis {
methods: Vec<GoMethodReference>,
modules: Vec<SdkModule>,
}
impl GoAnalysis {
#[must_use]
pub fn methods(&self) -> &[GoMethodReference] {
&self.methods
}
#[must_use]
pub fn modules(&self) -> &[SdkModule] {
&self.modules
}
}
pub fn analyze_dir(path: impl AsRef<Path>) -> Result<GoAnalysis, GoAnalysisError> {
let path = path.as_ref();
if !path.is_dir() {
return Err(GoAnalysisError::NotDirectory(path.to_path_buf()));
}
let path_str = path
.to_str()
.ok_or_else(|| GoAnalysisError::NonUtf8Path(path.to_path_buf()))?;
let path = CString::new(path_str).map_err(GoAnalysisError::InteriorNul)?;
let response_ptr = analyze_go(path.as_ptr());
if response_ptr.is_null() {
return Err(GoAnalysisError::NullResponse);
}
let response = AnalyzerResponseGuard::from_raw(response_ptr);
let response = response.as_c_str().to_str().map_err(|error| {
GoAnalysisError::Analyzer(format!("analyzer returned non-utf-8 response: {error}"))
})?;
let response: AnalyzerResponse =
serde_json::from_str(response).map_err(GoAnalysisError::InvalidResponse)?;
let (methods, modules) = response
.into_analysis()
.map_err(GoAnalysisError::Analyzer)?;
Ok(GoAnalysis { methods, modules })
}