use crate::error::common::OperationErrorKind;
use crate::error::metrics::MetricsError;
use crate::error::{GraphError, GreeksError, InterpolationError, OptionsError, PositionError};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum CurveError {
#[error("Error: {reason}")]
Point2DError {
reason: &'static str,
},
#[error("Operation error: {0}")]
OperationError(
OperationErrorKind,
),
#[error("rendering failed ({backend}): {reason}")]
RenderError {
backend: &'static str,
reason: String,
},
#[error("Interpolation error: {0}")]
InterpolationError(
String,
),
#[error("Construction error: {0}")]
ConstructionError(
String,
),
#[error("Analysis error: {0}")]
AnalysisError(
String,
),
#[error("Metrics error: {0}")]
MetricsError(
String,
),
#[error(transparent)]
Position(#[from] PositionError),
#[error(transparent)]
Options(#[from] OptionsError),
#[error(transparent)]
Greeks(#[from] GreeksError),
#[error("Interpolation error: {0}")]
InterpolationOp(String),
#[error(transparent)]
Graph(Box<GraphError>),
}
impl CurveError {
#[must_use]
#[cold]
#[inline(never)]
pub fn operation_not_supported(operation: &str, reason: &str) -> Self {
CurveError::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 {
CurveError::OperationError(OperationErrorKind::InvalidParameters {
operation: operation.to_string(),
reason: reason.to_string(),
})
}
}
pub type CurvesResult<T> = Result<T, CurveError>;
impl From<MetricsError> for CurveError {
fn from(err: MetricsError) -> Self {
CurveError::MetricsError(err.to_string())
}
}
impl From<InterpolationError> for CurveError {
fn from(err: InterpolationError) -> Self {
CurveError::InterpolationOp(err.to_string())
}
}
impl From<GraphError> for CurveError {
fn from(err: GraphError) -> Self {
CurveError::Graph(Box::new(err))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::error::Error;
#[test]
fn test_curves_error_display() {
let error = CurveError::Point2DError {
reason: "Invalid coordinates",
};
assert_eq!(error.to_string(), "Error: Invalid coordinates");
let error = CurveError::RenderError {
backend: "plotters",
reason: "rendering failed".to_string(),
};
assert_eq!(
error.to_string(),
"rendering failed (plotters): rendering failed"
);
let error = CurveError::operation_not_supported("calculate", "Strategy");
assert_eq!(
error.to_string(),
"Operation error: Operation 'calculate' is not supported for strategy 'Strategy'"
);
}
#[test]
fn test_operation_not_supported() {
let error = CurveError::operation_not_supported("test_op", "TestStrat");
match error {
CurveError::OperationError(OperationErrorKind::NotSupported {
operation,
reason: strategy_type,
}) => {
assert_eq!(operation, "test_op");
assert_eq!(strategy_type, "TestStrat");
}
_ => panic!("Wrong error variant"),
}
}
#[test]
fn test_invalid_parameters() {
let error = CurveError::invalid_parameters("test_op", "invalid input");
match error {
CurveError::OperationError(OperationErrorKind::InvalidParameters {
operation,
reason,
}) => {
assert_eq!(operation, "test_op");
assert_eq!(reason, "invalid input");
}
_ => panic!("Wrong error variant"),
}
}
#[test]
fn test_error_trait_implementation() {
let error = CurveError::Point2DError {
reason: "test error",
};
let error_ref: &dyn Error = &error;
assert_eq!(error_ref.to_string(), "Error: test error");
}
#[test]
fn test_render_error_constructor() {
let error = CurveError::RenderError {
backend: "plotters",
reason: "Draw error".to_string(),
};
match error {
CurveError::RenderError { backend, reason } => {
assert_eq!(backend, "plotters");
assert_eq!(reason, "Draw error");
}
_ => panic!("Wrong error variant"),
}
}
#[test]
fn test_from_position_error() {
let position_error = PositionError::unsupported_operation("TestStruct", "test_op");
let curves_error = CurveError::from(position_error);
match curves_error {
CurveError::Position(_) => {
}
_ => panic!("Wrong error variant"),
}
}
#[test]
fn test_debug_implementation() {
let error = CurveError::Point2DError {
reason: "test debug",
};
assert!(format!("{error:?}").contains("test debug"));
let error = CurveError::RenderError {
backend: "plotters",
reason: "test debug".to_string(),
};
assert!(format!("{error:?}").contains("test debug"));
}
}
#[cfg(test)]
mod tests_extended {
use super::*;
#[test]
fn test_curves_error_construction_error() {
let error =
CurveError::ConstructionError("Invalid curve construction parameters".to_string());
assert_eq!(
format!("{error}"),
"Construction error: Invalid curve construction parameters"
);
}
#[test]
fn test_curves_error_analysis_error() {
let error =
CurveError::AnalysisError("Analysis failed due to insufficient data".to_string());
assert_eq!(
format!("{error}"),
"Analysis error: Analysis failed due to insufficient data"
);
}
}