use crate::{
core::CoreError, linalg::LinAlgError, observers::ObserverError, optimizer::OptimizerError,
};
use apex_io::IoError;
use apex_manifolds::ManifoldError;
use std::error::Error as StdError;
use thiserror::Error;
pub type ApexSolverResult<T> = Result<T, ApexSolverError>;
#[derive(Debug, Error)]
pub enum ApexSolverError {
#[error(transparent)]
Core(#[from] CoreError),
#[error(transparent)]
Optimizer(#[from] OptimizerError),
#[error(transparent)]
LinearAlgebra(#[from] LinAlgError),
#[error(transparent)]
Manifold(#[from] ManifoldError),
#[error(transparent)]
Io(#[from] IoError),
#[error(transparent)]
Observer(#[from] ObserverError),
}
impl ApexSolverError {
pub fn chain(&self) -> String {
let mut chain = vec![self.to_string()];
let mut source = self.source();
while let Some(err) = source {
chain.push(format!(" → {}", err));
source = err.source();
}
chain.join("\n")
}
pub fn chain_compact(&self) -> String {
let mut chain = vec![self.to_string()];
let mut source = self.source();
while let Some(err) = source {
chain.push(err.to_string());
source = err.source();
}
chain.join(" → ")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_apex_solver_error_display() {
let linalg_error = LinAlgError::SingularMatrix("test singular matrix".to_string());
let error = ApexSolverError::from(linalg_error);
assert!(error.to_string().contains("Singular matrix"));
}
#[test]
fn test_apex_solver_error_chain() {
let linalg_error =
LinAlgError::FactorizationFailed("Cholesky factorization failed".to_string());
let error = ApexSolverError::from(linalg_error);
let chain = error.chain();
assert!(chain.contains("factorization"));
assert!(chain.contains("Cholesky"));
}
#[test]
fn test_apex_solver_error_chain_compact() {
let core_error = CoreError::Variable("Invalid variable index".to_string());
let error = ApexSolverError::from(core_error);
let chain_compact = error.chain_compact();
assert!(chain_compact.contains("Invalid variable index"));
}
#[test]
fn test_apex_solver_result_ok() {
let result: ApexSolverResult<i32> = Ok(42);
assert!(result.is_ok());
if let Ok(value) = result {
assert_eq!(value, 42);
}
}
#[test]
fn test_apex_solver_result_err() {
let core_error = CoreError::ResidualBlock("Test error".to_string());
let result: ApexSolverResult<i32> = Err(ApexSolverError::from(core_error));
assert!(result.is_err());
}
#[test]
fn test_transparent_error_conversion() {
let manifold_error = ManifoldError::DimensionMismatch {
expected: 3,
actual: 2,
};
let apex_error: ApexSolverError = manifold_error.into();
assert!(
matches!(apex_error, ApexSolverError::Manifold(_)),
"Expected Manifold variant"
);
}
}