someip_sd_wire/
error.rs

1/// Error type for SOME/IP-SD parsing and validation operations.
2///
3/// Represents different error conditions that can occur during parsing,
4/// validation, or serialization of SOME/IP-SD wire format data.
5///
6/// # Examples
7///
8/// ```
9/// use someip_sd_wire::error::Error;
10/// use someip_sd_wire::packet::Packet;
11///
12/// let buffer = [0u8; 4]; // Too small for a valid SD packet
13/// let result = Packet::new_checked(&buffer[..]);
14/// assert_eq!(result, Err(Error::BufferTooShort));
15/// ```
16#[derive(PartialEq, Debug, Clone, Copy, Eq)]
17pub enum Error {
18    /// Buffer is too short for the expected data structure.
19    ///
20    /// This occurs when:
21    /// - Packet buffer is smaller than minimum SD header (12 bytes)
22    /// - Entry buffer is smaller than entry size (16 bytes)
23    /// - Option buffer is smaller than expected option size
24    /// - Declared lengths exceed available buffer space
25    BufferTooShort,
26
27    /// Invalid entry type value.
28    ///
29    /// Entry type must be one of:
30    /// - 0x00: FindService
31    /// - 0x01: OfferService
32    /// - 0x06: Subscribe
33    /// - 0x07: SubscribeAck
34    InvalidEntryType(u8),
35
36    /// Invalid option type value.
37    ///
38    /// Option type must be one of the defined option types:
39    /// - 0x01: Configuration
40    /// - 0x02: LoadBalancing
41    /// - 0x04: IPv4Endpoint
42    /// - 0x06: IPv6Endpoint
43    /// - 0x14: IPv4Multicast
44    /// - 0x16: IPv6Multicast
45    /// - 0x24: IPv4SdEndpoint
46    /// - 0x26: IPv6SdEndpoint
47    InvalidOptionType(u8),
48
49    /// Invalid transport protocol value.
50    ///
51    /// Transport protocol must be:
52    /// - 0x06: TCP
53    /// - 0x11: UDP
54    InvalidProtocol(u8),
55
56    /// Length field overflow.
57    ///
58    /// This occurs when:
59    /// - Entries length + options length would overflow buffer
60    /// - Length fields have inconsistent values
61    /// - Option length field exceeds remaining buffer
62    LengthOverflow,
63
64    /// Invalid configuration entry format.
65    ///
66    /// Configuration entries must follow DNS-SD TXT record format.
67    /// This variant wraps configuration-specific errors.
68    ConfigurationError(ConfigError),
69}
70
71/// Configuration-specific error types.
72///
73/// These errors occur during parsing or serialization of DNS-SD TXT record
74/// style configuration options.
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub enum ConfigError {
77    /// Invalid key format.
78    ///
79    /// Keys must be:
80    /// - Non-empty
81    /// - Printable US-ASCII (0x20-0x7E)
82    /// - Not contain '=' character
83    /// - Contain at least one non-whitespace character
84    InvalidKey,
85
86    /// Key starts with '=' which is not allowed.
87    KeyStartsWithEquals,
88
89    /// Unexpected end of data while parsing.
90    ///
91    /// This occurs when a length byte is present but the corresponding
92    /// data is missing from the buffer.
93    UnexpectedEnd,
94
95    /// Length field would overflow buffer.
96    ///
97    /// The length prefix indicates more data than is available in
98    /// the remaining buffer.
99    LengthOverflow,
100
101    /// Buffer too small for serialization.
102    ///
103    /// The output buffer does not have enough space for the
104    /// serialized configuration data.
105    BufferTooSmall,
106
107    /// Invalid UTF-8 in string data.
108    ///
109    /// Configuration strings must be valid UTF-8.
110    InvalidUtf8,
111}
112
113impl From<ConfigError> for Error {
114    fn from(err: ConfigError) -> Self {
115        Error::ConfigurationError(err)
116    }
117}
118
119impl core::fmt::Display for Error {
120    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
121        match self {
122            Error::BufferTooShort => write!(f, "buffer too short for expected structure"),
123            Error::InvalidEntryType(t) => write!(f, "invalid entry type: 0x{:02x}", t),
124            Error::InvalidOptionType(t) => write!(f, "invalid option type: 0x{:02x}", t),
125            Error::InvalidProtocol(p) => write!(f, "invalid transport protocol: 0x{:02x}", p),
126            Error::LengthOverflow => write!(f, "length field overflow"),
127            Error::ConfigurationError(e) => write!(f, "configuration error: {}", e),
128        }
129    }
130}
131
132impl core::fmt::Display for ConfigError {
133    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134        match self {
135            ConfigError::InvalidKey => write!(f, "invalid key format"),
136            ConfigError::KeyStartsWithEquals => write!(f, "key starts with '='"),
137            ConfigError::UnexpectedEnd => write!(f, "unexpected end of data"),
138            ConfigError::LengthOverflow => write!(f, "length field overflow"),
139            ConfigError::BufferTooSmall => write!(f, "buffer too small"),
140            ConfigError::InvalidUtf8 => write!(f, "invalid UTF-8"),
141        }
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_error_display() {
151        assert_eq!(format!("{}", Error::BufferTooShort), "buffer too short for expected structure");
152        assert_eq!(format!("{}", Error::InvalidEntryType(0xFF)), "invalid entry type: 0xff");
153        assert_eq!(format!("{}", Error::InvalidOptionType(0xAB)), "invalid option type: 0xab");
154        assert_eq!(format!("{}", Error::InvalidProtocol(0x99)), "invalid transport protocol: 0x99");
155        assert_eq!(format!("{}", Error::LengthOverflow), "length field overflow");
156    }
157
158    #[test]
159    fn test_config_error_display() {
160        assert_eq!(format!("{}", ConfigError::InvalidKey), "invalid key format");
161        assert_eq!(format!("{}", ConfigError::KeyStartsWithEquals), "key starts with '='");
162        assert_eq!(format!("{}", ConfigError::UnexpectedEnd), "unexpected end of data");
163        assert_eq!(format!("{}", ConfigError::LengthOverflow), "length field overflow");
164        assert_eq!(format!("{}", ConfigError::BufferTooSmall), "buffer too small");
165        assert_eq!(format!("{}", ConfigError::InvalidUtf8), "invalid UTF-8");
166    }
167
168    #[test]
169    fn test_config_error_conversion() {
170        let config_err = ConfigError::InvalidKey;
171        let err: Error = config_err.into();
172        assert_eq!(err, Error::ConfigurationError(ConfigError::InvalidKey));
173    }
174
175    #[test]
176    fn test_error_equality() {
177        assert_eq!(Error::BufferTooShort, Error::BufferTooShort);
178        assert_ne!(Error::BufferTooShort, Error::LengthOverflow);
179        assert_eq!(Error::InvalidEntryType(0x05), Error::InvalidEntryType(0x05));
180        assert_ne!(Error::InvalidEntryType(0x05), Error::InvalidEntryType(0x06));
181    }
182
183    #[test]
184    fn test_error_clone_copy() {
185        let err = Error::BufferTooShort;
186        let err2 = err;
187        let err3 = err.clone();
188        assert_eq!(err, err2);
189        assert_eq!(err, err3);
190    }
191}