use thiserror::Error;
pub type Result<T> = std::result::Result<T, ForecastError>;
#[derive(Error, Debug, Clone, PartialEq)]
pub enum ForecastError {
#[error("empty input data")]
EmptyData,
#[error("insufficient data: need at least {needed}, got {got}")]
InsufficientData { needed: usize, got: usize },
#[error("invalid parameter: {0}")]
InvalidParameter(String),
#[error("dimension mismatch: expected {expected}, got {got}")]
DimensionMismatch { expected: usize, got: usize },
#[error("timestamp error: {0}")]
TimestampError(String),
#[error("model must be fitted before prediction")]
FitRequired,
#[error("missing values detected in data")]
MissingValues,
#[error("could not infer frequency: {0}")]
FrequencyInference(String),
#[error("index out of bounds: {index} (size: {size})")]
IndexOutOfBounds { index: usize, size: usize },
#[error("computation error: {0}")]
ComputationError(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_messages_are_descriptive() {
let err = ForecastError::EmptyData;
assert_eq!(err.to_string(), "empty input data");
let err = ForecastError::InsufficientData { needed: 10, got: 5 };
assert_eq!(
err.to_string(),
"insufficient data: need at least 10, got 5"
);
let err = ForecastError::InvalidParameter("window must be positive".to_string());
assert_eq!(
err.to_string(),
"invalid parameter: window must be positive"
);
let err = ForecastError::DimensionMismatch {
expected: 3,
got: 2,
};
assert_eq!(err.to_string(), "dimension mismatch: expected 3, got 2");
let err = ForecastError::FitRequired;
assert_eq!(err.to_string(), "model must be fitted before prediction");
}
#[test]
fn errors_are_clonable_and_comparable() {
let err1 = ForecastError::EmptyData;
let err2 = err1.clone();
assert_eq!(err1, err2);
}
}