openigtlink_rust/
error.rs

1//! Error types for OpenIGTLink protocol operations
2//!
3//! This module defines all error types that can occur during OpenIGTLink
4//! protocol operations, including network I/O, message parsing, and validation.
5
6use thiserror::Error;
7
8/// OpenIGTLink protocol error types
9///
10/// All operations in this library return `Result<T, IgtlError>` to provide
11/// explicit error handling.
12#[derive(Error, Debug)]
13pub enum IgtlError {
14    /// Invalid header format or content
15    ///
16    /// This error occurs when:
17    /// - Header version field is not 1, 2, or 3
18    /// - Message type contains invalid characters (non-ASCII or control characters)
19    /// - Device name contains invalid characters
20    /// - Header size doesn't match expected 58 bytes
21    ///
22    /// # Example
23    /// ```no_run
24    /// # use openigtlink_rust::error::IgtlError;
25    /// let err = IgtlError::InvalidHeader("Version must be 1, 2, or 3".to_string());
26    /// ```
27    #[error("Invalid header: {0}")]
28    InvalidHeader(String),
29
30    /// CRC checksum mismatch
31    ///
32    /// This error occurs when:
33    /// - Network transmission corrupted the message data
34    /// - Message was tampered with during transmission
35    /// - Sender and receiver use incompatible CRC implementations
36    /// - Hardware-level data corruption (rare)
37    ///
38    /// When this error occurs, the message should be discarded and the sender
39    /// should retransmit.
40    ///
41    /// # Example
42    /// ```no_run
43    /// # use openigtlink_rust::error::IgtlError;
44    /// let err = IgtlError::CrcMismatch {
45    ///     expected: 0x1234567890abcdef,
46    ///     actual: 0x1234567890abcdee,
47    /// };
48    /// ```
49    #[error("CRC mismatch: expected {expected:#x}, got {actual:#x}")]
50    CrcMismatch {
51        /// Expected CRC value calculated from message body
52        expected: u64,
53        /// Actual CRC value received in message header
54        actual: u64,
55    },
56
57    /// Unknown or unsupported message type
58    ///
59    /// This error occurs when:
60    /// - Receiving a message type not implemented in this library
61    /// - Message type field contains invalid characters
62    /// - Sender uses a custom/proprietary message type
63    /// - Protocol version mismatch (e.g., OpenIGTLink v4 message on v3 receiver)
64    ///
65    /// The 21 standard message types are supported. Custom message types
66    /// will trigger this error unless explicitly added.
67    ///
68    /// # Example
69    /// ```no_run
70    /// # use openigtlink_rust::error::IgtlError;
71    /// let err = IgtlError::UnknownMessageType("CUSTOM_MSG".to_string());
72    /// ```
73    #[error("Unknown message type: {0}")]
74    UnknownMessageType(String),
75
76    /// Invalid message size
77    ///
78    /// This error occurs when:
79    /// - Message body size doesn't match the size declared in header
80    /// - Required fields are missing in message body
81    /// - Array sizes in message don't match declared counts
82    /// - Message is truncated during transmission
83    ///
84    /// # Example
85    /// ```no_run
86    /// # use openigtlink_rust::error::IgtlError;
87    /// let err = IgtlError::InvalidSize {
88    ///     expected: 100,
89    ///     actual: 95,
90    /// };
91    /// ```
92    #[error("Invalid message size: expected {expected}, got {actual}")]
93    InvalidSize {
94        /// Expected size in bytes based on message format
95        expected: usize,
96        /// Actual size in bytes received or parsed
97        actual: usize,
98    },
99
100    /// I/O error occurred during network communication
101    ///
102    /// This error wraps standard library I/O errors and occurs when:
103    /// - TCP connection failed or was refused
104    /// - Connection lost during transmission (broken pipe)
105    /// - Network timeout occurred
106    /// - Socket was closed by peer
107    /// - Insufficient permissions to bind to port
108    ///
109    /// Common scenarios:
110    /// - Server not running at specified address
111    /// - Firewall blocking the connection
112    /// - Network cable unplugged during operation
113    /// - Server crashed during communication
114    ///
115    /// # Example
116    /// ```no_run
117    /// # use openigtlink_rust::error::IgtlError;
118    /// # use std::io;
119    /// let io_err = io::Error::new(io::ErrorKind::ConnectionRefused, "Connection refused");
120    /// let err = IgtlError::Io(io_err);
121    /// ```
122    #[error("I/O error: {0}")]
123    Io(#[from] std::io::Error),
124
125    /// UTF-8 conversion error
126    ///
127    /// This error occurs when:
128    /// - Device name or string message contains invalid UTF-8 sequences
129    /// - Message was created by non-UTF-8 compliant sender
130    /// - Data corruption in text fields
131    ///
132    /// OpenIGTLink string fields should be UTF-8 encoded. This error
133    /// indicates the sender is not following the specification.
134    ///
135    /// # Example
136    /// ```no_run
137    /// # use openigtlink_rust::error::IgtlError;
138    /// let invalid_bytes = vec![0xFF, 0xFE, 0xFD];
139    /// match String::from_utf8(invalid_bytes) {
140    ///     Err(e) => {
141    ///         let err = IgtlError::Utf8(e);
142    ///     }
143    ///     _ => {}
144    /// }
145    /// ```
146    #[error("UTF-8 conversion error: {0}")]
147    Utf8(#[from] std::string::FromUtf8Error),
148
149    /// Invalid timestamp value
150    ///
151    /// This error occurs when:
152    /// - Timestamp nanoseconds field exceeds 10^9 (invalid)
153    /// - Timestamp seconds field is negative (if checked)
154    /// - Timestamp represents a date far in the future (system time issue)
155    ///
156    /// # Example
157    /// ```no_run
158    /// # use openigtlink_rust::error::IgtlError;
159    /// let err = IgtlError::InvalidTimestamp("Nanoseconds must be < 1000000000".to_string());
160    /// ```
161    #[error("Invalid timestamp: {0}")]
162    InvalidTimestamp(String),
163
164    /// Message body size exceeds maximum allowed
165    ///
166    /// This error occurs when:
167    /// - Attempting to send a message larger than protocol limit (typically 4GB)
168    /// - Image data exceeds reasonable memory limits
169    /// - Malformed message header declares impossibly large body size
170    ///
171    /// This protects against memory exhaustion attacks and implementation bugs.
172    ///
173    /// # Example
174    /// ```no_run
175    /// # use openigtlink_rust::error::IgtlError;
176    /// let err = IgtlError::BodyTooLarge {
177    ///     size: 5_000_000_000,
178    ///     max: 4_294_967_295,
179    /// };
180    /// ```
181    #[error("Message body too large: {size} bytes (max: {max})")]
182    BodyTooLarge {
183        /// Actual body size in bytes
184        size: usize,
185        /// Maximum allowed size in bytes
186        max: usize,
187    },
188}
189
190/// Result type alias for OpenIGTLink operations
191pub type Result<T> = std::result::Result<T, IgtlError>;