kizzasi_tokenizer/
error.rs1use thiserror::Error;
7
8pub type TokenizerResult<T> = Result<T, TokenizerError>;
10
11#[derive(Error, Debug)]
13pub enum TokenizerError {
14 #[error("Invalid configuration: {0}")]
19 InvalidConfig(String),
20
21 #[error("Dimension mismatch in {context}: expected {expected}, got {got}")]
26 DimensionMismatch {
27 expected: usize,
28 got: usize,
29 context: String,
30 },
31
32 #[error("Encoding failed in {operation}: {reason}")]
37 EncodingError { operation: String, reason: String },
38
39 #[error("Decoding failed in {operation}: {reason}")]
43 DecodingError { operation: String, reason: String },
44
45 #[error("Codebook not initialized: {hint}")]
50 CodebookNotInitialized { hint: String },
51
52 #[error("Value out of range in {context}: {value} not in [{min}, {max}]")]
56 ValueOutOfRange {
57 value: f32,
58 min: f32,
59 max: f32,
60 context: String,
61 },
62
63 #[cfg(not(target_arch = "wasm32"))]
65 #[error("Core error: {0}")]
66 CoreError(#[from] kizzasi_core::CoreError),
67
68 #[error("Internal error (please report this): {0}")]
73 InternalError(String),
74
75 #[error("Invalid input in {operation}: {reason}")]
80 InvalidInput { operation: String, reason: String },
81
82 #[error("Serialization error: {0}")]
84 SerializationError(String),
85
86 #[error("I/O error: {0}")]
88 IoError(#[from] std::io::Error),
89
90 #[error("Training error at epoch {epoch}: {reason}")]
92 TrainingError { epoch: usize, reason: String },
93
94 #[error("Numerical error in {operation}: {reason}")]
96 NumericalError { operation: String, reason: String },
97
98 #[error("Resource limit exceeded: {resource} - {details}")]
100 ResourceLimitExceeded { resource: String, details: String },
101
102 #[error("Feature not implemented: {0}")]
104 NotImplemented(String),
105}
106
107impl TokenizerError {
108 pub fn dim_mismatch(expected: usize, got: usize, context: impl Into<String>) -> Self {
110 Self::DimensionMismatch {
111 expected,
112 got,
113 context: context.into(),
114 }
115 }
116
117 pub fn encoding(operation: impl Into<String>, reason: impl Into<String>) -> Self {
119 Self::EncodingError {
120 operation: operation.into(),
121 reason: reason.into(),
122 }
123 }
124
125 pub fn decoding(operation: impl Into<String>, reason: impl Into<String>) -> Self {
127 Self::DecodingError {
128 operation: operation.into(),
129 reason: reason.into(),
130 }
131 }
132
133 pub fn out_of_range(value: f32, min: f32, max: f32, context: impl Into<String>) -> Self {
135 Self::ValueOutOfRange {
136 value,
137 min,
138 max,
139 context: context.into(),
140 }
141 }
142
143 pub fn invalid_input(operation: impl Into<String>, reason: impl Into<String>) -> Self {
145 Self::InvalidInput {
146 operation: operation.into(),
147 reason: reason.into(),
148 }
149 }
150
151 pub fn numerical(operation: impl Into<String>, reason: impl Into<String>) -> Self {
153 Self::NumericalError {
154 operation: operation.into(),
155 reason: reason.into(),
156 }
157 }
158
159 pub fn training(epoch: usize, reason: impl Into<String>) -> Self {
161 Self::TrainingError {
162 epoch,
163 reason: reason.into(),
164 }
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_error_messages() {
174 let err = TokenizerError::dim_mismatch(10, 20, "input validation");
175 assert!(err.to_string().contains("10"));
176 assert!(err.to_string().contains("20"));
177 assert!(err.to_string().contains("input validation"));
178
179 let err2 = TokenizerError::encoding("VQ-VAE", "codebook lookup failed");
180 assert!(err2.to_string().contains("VQ-VAE"));
181 assert!(err2.to_string().contains("codebook lookup failed"));
182 }
183
184 #[test]
185 fn test_helper_constructors() {
186 let err = TokenizerError::out_of_range(1.5, 0.0, 1.0, "quantization");
187 assert!(matches!(err, TokenizerError::ValueOutOfRange { .. }));
188
189 let err2 = TokenizerError::invalid_input("encode", "empty array");
190 assert!(matches!(err2, TokenizerError::InvalidInput { .. }));
191 }
192}