use crate::error::{
GraphError, GreeksError, InterpolationError, OperationErrorKind, OptionsError, PositionError,
};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum SurfaceError {
#[error("Error: {reason}")]
Point3DError {
reason: &'static str,
},
#[error("Operation error: {0}")]
OperationError(OperationErrorKind),
#[error("rendering failed ({backend}): {reason}")]
RenderError {
backend: &'static str,
reason: String,
},
#[error("Construction error: {0}")]
ConstructionError(String),
#[error("Analysis error: {0}")]
AnalysisError(String),
#[error(transparent)]
Position(#[from] PositionError),
#[error(transparent)]
Options(#[from] OptionsError),
#[error(transparent)]
Greeks(#[from] GreeksError),
#[error(transparent)]
Graph(Box<GraphError>),
}
impl SurfaceError {
#[must_use]
#[cold]
#[inline(never)]
pub fn operation_not_supported(operation: &str, reason: &str) -> Self {
SurfaceError::OperationError(OperationErrorKind::NotSupported {
operation: operation.to_string(),
reason: reason.to_string(),
})
}
#[must_use]
#[cold]
#[inline(never)]
pub fn invalid_parameters(operation: &str, reason: &str) -> Self {
SurfaceError::OperationError(OperationErrorKind::InvalidParameters {
operation: operation.to_string(),
reason: reason.to_string(),
})
}
}
impl From<InterpolationError> for SurfaceError {
fn from(err: InterpolationError) -> Self {
SurfaceError::AnalysisError(err.to_string())
}
}
impl From<GraphError> for SurfaceError {
fn from(err: GraphError) -> Self {
SurfaceError::Graph(Box::new(err))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::CurveError;
use crate::error::curves::CurvesResult;
use crate::error::position::PositionValidationErrorKind;
#[test]
fn test_operation_not_supported() {
let error = SurfaceError::operation_not_supported(
"test_operation",
"Operation cannot be performed",
);
match error {
SurfaceError::OperationError(OperationErrorKind::NotSupported {
operation,
reason,
}) => {
assert_eq!(operation, "test_operation");
assert_eq!(reason, "Operation cannot be performed");
}
_ => panic!("Wrong error variant"),
}
}
#[test]
fn test_invalid_parameters() {
let error = SurfaceError::invalid_parameters("test_params", "Invalid input parameters");
match error {
SurfaceError::OperationError(OperationErrorKind::InvalidParameters {
operation,
reason,
}) => {
assert_eq!(operation, "test_params");
assert_eq!(reason, "Invalid input parameters");
}
_ => panic!("Wrong error variant"),
}
}
#[test]
fn test_display_operation_error() {
let error = SurfaceError::operation_not_supported(
"test_operation",
"Operation cannot be performed",
);
assert!(error.to_string().contains("Operation error"));
assert!(error.to_string().contains("test_operation"));
assert!(error.to_string().contains("Operation cannot be performed"));
}
#[test]
fn test_display_render_error() {
let error = SurfaceError::RenderError {
backend: "plotters",
reason: "rendering failed".to_string(),
};
assert_eq!(
error.to_string(),
"rendering failed (plotters): rendering failed"
);
}
#[test]
fn test_display_point3d_error() {
let error = SurfaceError::Point3DError {
reason: "Point error test",
};
assert_eq!(error.to_string(), "Error: Point error test");
}
#[test]
fn test_display_construction_error() {
let error = SurfaceError::ConstructionError("Construction failed".to_string());
assert_eq!(error.to_string(), "Construction error: Construction failed");
}
#[test]
fn test_display_analysis_error() {
let error = SurfaceError::AnalysisError("Analysis failed".to_string());
assert_eq!(error.to_string(), "Analysis error: Analysis failed");
}
#[test]
fn test_from_position_error() {
let pos_error =
PositionError::ValidationError(PositionValidationErrorKind::InvalidPosition {
reason: "Test position error".to_string(),
});
let surface_error = SurfaceError::from(pos_error);
match surface_error {
SurfaceError::Position(_) => {
}
_ => panic!("Expected Position variant"),
}
}
#[test]
fn test_from_interpolation_error_surfaces() {
let interpolation_err = InterpolationError::EmptyData;
let surface_err = SurfaceError::from(interpolation_err);
assert!(matches!(surface_err, SurfaceError::AnalysisError(_)));
}
#[test]
fn test_curves_result_err() {
let result: CurvesResult<i32> = Err(CurveError::AnalysisError("Test error".to_string()));
assert!(result.is_err());
match result {
Err(err) => {
assert_eq!(err.to_string(), "Analysis error: Test error");
}
Ok(_) => panic!("Expected an error result"),
}
}
#[test]
fn test_curves_result_err_alternative() {
let err = CurveError::AnalysisError("Test error".to_string());
assert_eq!(err.to_string(), "Analysis error: Test error");
let result: CurvesResult<i32> = Err(err);
assert!(result.is_err());
match result {
Err(e) => {
assert_eq!(e.to_string(), "Analysis error: Test error");
}
Ok(_) => panic!("Expected an error result"),
}
}
}