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>;