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("Error: {reason}")]
StdError {
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 {
pub fn operation_not_supported(operation: &str, reason: &str) -> Self {
SurfaceError::OperationError(OperationErrorKind::NotSupported {
operation: operation.to_string(),
reason: reason.to_string(),
})
}
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::StdError {
reason: err.to_string(),
}
}
}
impl From<GraphError> for SurfaceError {
fn from(err: GraphError) -> Self {
SurfaceError::Graph(Box::new(err))
}
}
impl From<Box<dyn std::error::Error>> for SurfaceError {
fn from(err: Box<dyn std::error::Error>) -> Self {
SurfaceError::StdError {
reason: err.to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::CurveError;
use crate::error::curves::CurvesResult;
use crate::error::position::PositionValidationErrorKind;
#[derive(Debug)]
struct TestError {
message: String,
}
impl std::fmt::Display for TestError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for TestError {}
#[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_std_error() {
let error = SurfaceError::StdError {
reason: "Standard error test".to_string(),
};
assert_eq!(error.to_string(), "Error: Standard error test");
}
#[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_box_dyn_error() {
let test_error = TestError {
message: "Test box error".to_string(),
};
let boxed_error: Box<dyn std::error::Error> = Box::new(test_error);
let surface_error = SurfaceError::from(boxed_error);
match surface_error {
SurfaceError::StdError { reason } => {
assert_eq!(reason, "Test box error");
}
_ => panic!("Wrong error variant"),
}
}
#[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"),
}
}
}