train_station/serialization/core/
error.rs

1//! Core error types for serialization operations
2//!
3//! This module provides the fundamental error types and result aliases used throughout
4//! the serialization system. It defines the main `SerializationError` enum that covers
5//! all possible failure modes during serialization and deserialization operations.
6//!
7//! # Purpose
8//!
9//! The error system provides:
10//! - Comprehensive error coverage for all serialization operations
11//! - Detailed context for debugging and error recovery
12//! - Format-specific error delegation to specialized modules
13//! - Standard error trait implementations for integration
14//! - Convenient result type aliases for cleaner code
15//!
16//! # Error Categories
17//!
18//! The `SerializationError` enum covers several categories of errors:
19//! - **I/O Errors**: File operations, network issues, stream handling
20//! - **Format Errors**: JSON and binary format-specific parsing errors
21//! - **Validation Errors**: Data validation failures during deserialization
22//! - **Shape Errors**: Tensor dimension mismatches
23//! - **Memory Errors**: Allocation failures and resource constraints
24//! - **Custom Errors**: Generic errors with custom messages
25//!
26//! # Usage Patterns
27//!
28//! The error system provides comprehensive error handling for all serialization
29//! operations with detailed context for debugging and error recovery.
30//!
31//! # Error Handling
32//!
33//! All serialization operations return `SerializationResult<T>` which provides:
34//! - Detailed error context for debugging
35//! - Source error chaining for root cause analysis
36//! - Human-readable error messages
37//! - Structured error data for programmatic handling
38//!
39//! # Thread Safety
40//!
41//! All error types are thread-safe and can be shared across threads without
42//! additional synchronization.
43
44use std::fmt;
45use std::io;
46
47/// Result type for serialization operations
48///
49/// This type alias provides a convenient way to express the result of any
50/// serialization or deserialization operation. It uses the standard `Result`
51/// type with `SerializationError` as the error variant.
52pub type SerializationResult<T> = Result<T, SerializationError>;
53
54/// Main error type for serialization operations
55///
56/// This enum covers all possible failure modes during serialization and deserialization,
57/// providing detailed context for debugging and error recovery. Format-specific errors
58/// are delegated to their respective modules while maintaining a unified error interface.
59///
60/// # Error Variants
61///
62/// The enum provides comprehensive coverage of serialization failure modes:
63/// - **I/O errors**: File operations, network issues, stream handling
64/// - **Format errors**: JSON and binary format-specific parsing errors
65/// - **Validation errors**: Data validation failures during deserialization
66/// - **Shape errors**: Tensor dimension mismatches
67/// - **Memory errors**: Allocation failures and resource constraints
68/// - **Custom errors**: Generic errors with custom messages
69///
70/// # Error Context
71///
72/// Each error variant provides detailed context to aid in debugging:
73/// - Field names and validation messages for validation errors
74/// - Expected vs actual tensor dimensions for shape errors
75/// - Memory allocation details for allocation failures
76/// - Format-specific error information for parsing errors
77///
78/// # Thread Safety
79///
80/// This type is thread-safe and can be shared across threads without
81/// additional synchronization.
82///
83
84#[derive(Debug)]
85pub enum SerializationError {
86    /// I/O errors during file operations, network issues, or stream handling
87    ///
88    /// This variant wraps standard I/O errors that occur during serialization
89    /// operations, such as file reading/writing, network communication, or
90    /// stream processing. The underlying I/O error is preserved for detailed
91    /// error analysis.
92    ///
93    /// # Common Causes
94    ///
95    /// - File not found or permission denied
96    /// - Disk space exhaustion
97    /// - Network connectivity issues
98    /// - Stream corruption or interruption
99    /// - Device I/O failures
100    Io(io::Error),
101
102    /// JSON-specific format and parsing errors
103    ///
104    /// This variant delegates to the JSON module's error type for format-specific
105    /// JSON parsing and validation errors. It provides detailed information about
106    /// JSON syntax errors, structural issues, and parsing failures.
107    ///
108    /// # Common Causes
109    ///
110    /// - Invalid JSON syntax
111    /// - Malformed JSON structure
112    /// - Encoding issues
113    /// - Unexpected token types
114    /// - JSON depth limits exceeded
115    Json(crate::serialization::json::JsonError),
116
117    /// Binary-specific format and parsing errors
118    ///
119    /// This variant delegates to the binary module's error type for format-specific
120    /// binary parsing and validation errors. It provides detailed information about
121    /// binary format issues, corruption, and parsing failures.
122    ///
123    /// # Common Causes
124    ///
125    /// - Invalid binary format
126    /// - Corrupted binary data
127    /// - Version mismatches
128    /// - Magic number validation failures
129    /// - Truncated binary streams
130    Binary(crate::serialization::binary::BinaryError),
131
132    /// Data validation failed during deserialization
133    ///
134    /// This variant indicates that data validation failed during the deserialization
135    /// process. It provides the specific field name and a human-readable message
136    /// explaining why the validation failed.
137    ///
138    /// # Fields
139    ///
140    /// * `field` - Name of the field that failed validation
141    /// * `message` - Human-readable message explaining why validation failed
142    ///
143    /// # Common Causes
144    ///
145    /// - Invalid field values
146    /// - Missing required fields
147    /// - Type conversion failures
148    /// - Constraint violations
149    /// - Business logic validation failures
150    ValidationFailed {
151        /// Name of the field that failed validation
152        field: String,
153        /// Human-readable message explaining why validation failed
154        message: String,
155    },
156
157    /// Tensor shape or size mismatch
158    ///
159    /// This variant indicates that a tensor's dimensions don't match the expected
160    /// shape during deserialization or validation. It provides both the expected
161    /// and actual dimensions for debugging.
162    ///
163    /// # Fields
164    ///
165    /// * `expected_dims` - Expected tensor dimensions
166    /// * `found_dims` - Actual tensor dimensions found
167    ///
168    /// # Common Causes
169    ///
170    /// - Incorrect tensor serialization
171    /// - Version incompatibilities
172    /// - Manual data corruption
173    /// - Serialization format changes
174    /// - Dimension calculation errors
175    ShapeMismatch {
176        /// Expected tensor dimensions
177        expected_dims: Vec<usize>,
178        /// Actual tensor dimensions found
179        found_dims: Vec<usize>,
180    },
181
182    /// Memory allocation failed
183    ///
184    /// This variant indicates that a memory allocation request failed during
185    /// serialization or deserialization. It provides details about the requested
186    /// size and available memory (if known).
187    ///
188    /// # Fields
189    ///
190    /// * `requested_size` - Number of bytes that were requested
191    /// * `available_memory` - Number of bytes available (if known)
192    ///
193    /// # Common Causes
194    ///
195    /// - Insufficient system memory
196    /// - Memory fragmentation
197    /// - Resource limits exceeded
198    /// - Large tensor allocations
199    /// - Memory pool exhaustion
200    AllocationFailed {
201        /// Number of bytes that were requested
202        requested_size: usize,
203        /// Number of bytes available (if known)
204        available_memory: Option<usize>,
205    },
206
207    /// Generic error with custom message
208    ///
209    /// This variant provides a catch-all for generic serialization errors that
210    /// don't fit into the other specific categories. It allows for custom error
211    /// messages while maintaining the unified error interface.
212    ///
213    /// # Common Uses
214    ///
215    /// - Custom validation logic
216    /// - Business rule violations
217    /// - Unsupported operations
218    /// - Configuration errors
219    /// - Third-party integration issues
220    Custom(String),
221
222    // Compatibility variants - these will be removed after refactoring
223    /// @deprecated Use Json(JsonError::Format) instead
224    ///
225    /// This variant is deprecated and will be removed in a future version.
226    /// Use `Json(JsonError::Format)` instead for JSON format errors.
227    ///
228    /// # Migration
229    ///
230    /// Replace usage with the new format-specific error variants.
231    JsonFormat {
232        message: String,
233        line: Option<usize>,
234        column: Option<usize>,
235    },
236
237    /// @deprecated Use Binary(BinaryError::Format) instead
238    ///
239    /// This variant is deprecated and will be removed in a future version.
240    /// Use `Binary(BinaryError::Format)` instead for binary format errors.
241    ///
242    /// # Migration
243    ///
244    /// Replace usage with the new format-specific error variants.
245    BinaryFormat {
246        message: String,
247        position: Option<usize>,
248    },
249
250    /// @deprecated Use Binary(BinaryError::VersionMismatch) instead
251    ///
252    /// This variant is deprecated and will be removed in a future version.
253    /// Use `Binary(BinaryError::VersionMismatch)` instead for version mismatch errors.
254    ///
255    /// # Migration
256    ///
257    /// Replace usage with the new format-specific error variants.
258    VersionMismatch { expected: u32, found: u32 },
259
260    /// @deprecated Use Binary(BinaryError::InvalidMagic) instead
261    ///
262    /// This variant is deprecated and will be removed in a future version.
263    /// Use `Binary(BinaryError::InvalidMagic)` instead for invalid magic number errors.
264    ///
265    /// # Migration
266    ///
267    /// Replace usage with the new format-specific error variants.
268    InvalidMagic { expected: u32, found: u32 },
269}
270
271impl fmt::Display for SerializationError {
272    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273        match self {
274            SerializationError::Io(err) => {
275                write!(f, "I/O error during serialization: {}", err)
276            }
277            SerializationError::Json(err) => {
278                write!(f, "JSON error: {}", err)
279            }
280            SerializationError::Binary(err) => {
281                write!(f, "Binary error: {}", err)
282            }
283            SerializationError::ValidationFailed { field, message } => {
284                write!(f, "Validation failed for field '{}': {}", field, message)
285            }
286            SerializationError::ShapeMismatch {
287                expected_dims,
288                found_dims,
289            } => {
290                write!(
291                    f,
292                    "Shape mismatch: expected {:?}, found {:?}",
293                    expected_dims, found_dims
294                )
295            }
296            SerializationError::AllocationFailed {
297                requested_size,
298                available_memory,
299            } => match available_memory {
300                Some(available) => {
301                    write!(
302                        f,
303                        "Memory allocation failed: requested {} bytes, {} bytes available",
304                        requested_size, available
305                    )
306                }
307                None => {
308                    write!(
309                        f,
310                        "Memory allocation failed: requested {} bytes",
311                        requested_size
312                    )
313                }
314            },
315            SerializationError::Custom(message) => {
316                write!(f, "Serialization error: {}", message)
317            }
318            // Compatibility variants
319            SerializationError::JsonFormat {
320                message,
321                line,
322                column,
323            } => match (line, column) {
324                (Some(l), Some(c)) => {
325                    write!(
326                        f,
327                        "JSON format error at line {}, column {}: {}",
328                        l, c, message
329                    )
330                }
331                (Some(l), None) => {
332                    write!(f, "JSON format error at line {}: {}", l, message)
333                }
334                _ => {
335                    write!(f, "JSON format error: {}", message)
336                }
337            },
338            SerializationError::BinaryFormat { message, position } => match position {
339                Some(pos) => {
340                    write!(f, "Binary format error at position {}: {}", pos, message)
341                }
342                None => {
343                    write!(f, "Binary format error: {}", message)
344                }
345            },
346            SerializationError::VersionMismatch { expected, found } => {
347                write!(
348                    f,
349                    "Version mismatch: expected {}, found {}",
350                    expected, found
351                )
352            }
353            SerializationError::InvalidMagic { expected, found } => {
354                write!(
355                    f,
356                    "Invalid magic number: expected 0x{:08X}, found 0x{:08X}",
357                    expected, found
358                )
359            }
360        }
361    }
362}
363
364impl std::error::Error for SerializationError {
365    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
366        match self {
367            SerializationError::Io(err) => Some(err),
368            SerializationError::Json(err) => Some(err),
369            SerializationError::Binary(err) => Some(err),
370            _ => None,
371        }
372    }
373}
374
375impl From<io::Error> for SerializationError {
376    /// Convert an I/O error to a SerializationError
377    ///
378    /// This implementation allows I/O errors to be automatically converted
379    /// to SerializationError instances, enabling seamless error propagation
380    /// in serialization operations.
381    fn from(err: io::Error) -> Self {
382        SerializationError::Io(err)
383    }
384}
385
386impl From<crate::serialization::json::JsonError> for SerializationError {
387    /// Convert a JSON error to a SerializationError
388    ///
389    /// This implementation allows JSON-specific errors to be automatically
390    /// converted to SerializationError instances, maintaining error context
391    /// while providing a unified error interface.
392    fn from(err: crate::serialization::json::JsonError) -> Self {
393        SerializationError::Json(err)
394    }
395}
396
397impl From<crate::serialization::binary::BinaryError> for SerializationError {
398    /// Convert a binary error to a SerializationError
399    ///
400    /// This implementation allows binary-specific errors to be automatically
401    /// converted to SerializationError instances, maintaining error context
402    /// while providing a unified error interface.
403    fn from(err: crate::serialization::binary::BinaryError) -> Self {
404        SerializationError::Binary(err)
405    }
406}
407
408impl From<String> for SerializationError {
409    /// Convert a String to a SerializationError
410    ///
411    /// This implementation allows String values to be automatically converted
412    /// to SerializationError::Custom instances, providing a convenient way
413    /// to create custom error messages.
414    fn from(message: String) -> Self {
415        SerializationError::Custom(message)
416    }
417}
418
419impl From<&str> for SerializationError {
420    /// Convert a string slice to a SerializationError
421    ///
422    /// This implementation allows string slices to be automatically converted
423    /// to SerializationError::Custom instances, providing a convenient way
424    /// to create custom error messages from string literals.
425    fn from(message: &str) -> Self {
426        SerializationError::Custom(message.to_string())
427    }
428}
429
430impl SerializationError {
431    /// Create a JSON format error
432    ///
433    /// This method provides a convenient way to create JSON format errors
434    /// with optional line and column information for debugging.
435    ///
436    /// # Arguments
437    ///
438    /// * `message` - Human-readable error message describing the JSON format problem
439    /// * `line` - Line number where the error occurred (1-based, if available)
440    /// * `column` - Column number where the error occurred (1-based, if available)
441    ///
442    /// # Returns
443    ///
444    /// A SerializationError::Json variant with the specified format error
445    #[track_caller]
446    pub fn json_format(message: String, line: Option<usize>, column: Option<usize>) -> Self {
447        SerializationError::Json(crate::serialization::json::JsonError::Format {
448            message,
449            line,
450            column,
451        })
452    }
453
454    /// Create a binary format error
455    ///
456    /// This method provides a convenient way to create binary format errors
457    /// with optional position information for debugging.
458    ///
459    /// # Arguments
460    ///
461    /// * `message` - Human-readable error message describing the binary format problem
462    /// * `position` - Byte position where the error occurred (if available)
463    ///
464    /// # Returns
465    ///
466    /// A SerializationError::Binary variant with the specified format error
467    #[track_caller]
468    pub fn binary_format(message: String, position: Option<usize>) -> Self {
469        SerializationError::Binary(crate::serialization::binary::BinaryError::Format {
470            message,
471            position,
472        })
473    }
474
475    /// Create a binary version mismatch error
476    ///
477    /// This method provides a convenient way to create binary version mismatch
478    /// errors when the expected and actual format versions don't match.
479    ///
480    /// # Arguments
481    ///
482    /// * `expected` - Expected format version that the deserializer supports
483    /// * `found` - Actual format version found in the binary data
484    ///
485    /// # Returns
486    ///
487    /// A SerializationError::Binary variant with the specified version mismatch error
488    #[track_caller]
489    pub fn binary_version_mismatch(expected: u32, found: u32) -> Self {
490        SerializationError::Binary(crate::serialization::binary::BinaryError::VersionMismatch {
491            expected,
492            found,
493        })
494    }
495
496    /// Create a binary invalid magic error
497    ///
498    /// This method provides a convenient way to create binary invalid magic
499    /// errors when the binary data doesn't start with the expected magic number.
500    ///
501    /// # Arguments
502    ///
503    /// * `expected` - Expected magic number value for the binary format
504    /// * `found` - Actual magic number found at the beginning of the data
505    ///
506    /// # Returns
507    ///
508    /// A SerializationError::Binary variant with the specified invalid magic error
509    #[track_caller]
510    pub fn binary_invalid_magic(expected: u32, found: u32) -> Self {
511        SerializationError::Binary(crate::serialization::binary::BinaryError::InvalidMagic {
512            expected,
513            found,
514        })
515    }
516}