irithyll/error.rs
1//! Error types for Irithyll.
2
3use thiserror::Error;
4
5// ---------------------------------------------------------------------------
6// ConfigError -- structured sub-enum for configuration validation
7// ---------------------------------------------------------------------------
8
9/// Structured error for configuration validation failures.
10///
11/// Instead of opaque strings, each variant carries the parameter name and
12/// constraint so callers can programmatically inspect what went wrong.
13#[derive(Debug, Clone, Error)]
14pub enum ConfigError {
15 /// A parameter value is outside its valid range.
16 ///
17 /// # Examples
18 ///
19 /// ```text
20 /// n_steps must be > 0 (got 0)
21 /// learning_rate must be in (0, 1] (got 1.5)
22 /// ```
23 #[error("{param} {constraint} (got {value})")]
24 OutOfRange {
25 /// The parameter name (e.g. `"n_steps"`, `"drift_detector.Adwin.delta"`).
26 param: &'static str,
27 /// The constraint that was violated (e.g. `"must be > 0"`).
28 constraint: &'static str,
29 /// The actual value that was provided.
30 value: String,
31 },
32
33 /// A parameter is invalid for a structural reason, typically involving
34 /// a relationship between two parameters.
35 ///
36 /// # Examples
37 ///
38 /// ```text
39 /// split_reeval_interval must be >= grace_period (200), got 50
40 /// drift_detector.Ddm.drift_level must be > warning_level (3.0), got 2.0
41 /// ```
42 #[error("{param} {reason}")]
43 Invalid {
44 /// The parameter name.
45 param: &'static str,
46 /// Why the value is invalid.
47 reason: String,
48 },
49}
50
51impl ConfigError {
52 /// Convenience for the common "value out of range" case.
53 pub fn out_of_range(
54 param: &'static str,
55 constraint: &'static str,
56 value: impl ToString,
57 ) -> Self {
58 ConfigError::OutOfRange {
59 param,
60 constraint,
61 value: value.to_string(),
62 }
63 }
64
65 /// Convenience for the "invalid relationship" case.
66 pub fn invalid(param: &'static str, reason: impl Into<String>) -> Self {
67 ConfigError::Invalid {
68 param,
69 reason: reason.into(),
70 }
71 }
72}
73
74// ---------------------------------------------------------------------------
75// IrithyllError -- top-level error enum
76// ---------------------------------------------------------------------------
77
78/// Top-level error type for the Irithyll crate.
79#[derive(Debug, Error)]
80pub enum IrithyllError {
81 /// Configuration validation failed.
82 #[error("invalid configuration: {0}")]
83 InvalidConfig(#[from] ConfigError),
84
85 /// Not enough data to perform the requested operation.
86 #[error("insufficient data: {0}")]
87 InsufficientData(String),
88
89 /// Feature dimension mismatch between sample and model.
90 #[error("dimension mismatch: expected {expected}, got {got}")]
91 DimensionMismatch { expected: usize, got: usize },
92
93 /// Model has not been trained yet.
94 #[error("model not trained")]
95 NotTrained,
96
97 /// Serialization or deserialization failed.
98 #[error("serialization error: {0}")]
99 Serialization(String),
100
101 /// Async channel closed unexpectedly.
102 #[error("channel closed")]
103 ChannelClosed,
104}
105
106pub type Result<T> = std::result::Result<T, IrithyllError>;