1use std::io;
7
8pub type Result<T> = std::result::Result<T, GribError>;
10
11#[derive(Debug, thiserror::Error)]
13pub enum GribError {
14 #[error("I/O error: {0}")]
16 Io(#[from] io::Error),
17
18 #[error("Invalid GRIB header: expected 'GRIB' magic bytes, found {0:?}")]
20 InvalidHeader(Vec<u8>),
21
22 #[error("Unsupported GRIB edition: {0} (only GRIB1 and GRIB2 are supported)")]
24 UnsupportedEdition(u8),
25
26 #[error("Invalid section number: {0}")]
28 InvalidSection(u8),
29
30 #[error("Missing required section: {0}")]
32 MissingSection(String),
33
34 #[error("Invalid section length: expected at least {expected}, got {actual}")]
36 InvalidSectionLength {
37 expected: usize,
39 actual: usize,
41 },
42
43 #[error("Unsupported grid definition template: {0}")]
45 UnsupportedGridTemplate(u16),
46
47 #[error("Unsupported product definition template: {0}")]
49 UnsupportedProductTemplate(u16),
50
51 #[error("Unsupported data representation template: {0}")]
53 UnsupportedDataTemplate(u16),
54
55 #[error("Invalid parameter: discipline={discipline}, category={category}, number={number}")]
57 InvalidParameter {
58 discipline: u8,
60 category: u8,
62 number: u8,
64 },
65
66 #[error("Invalid grid definition: {0}")]
68 InvalidGrid(String),
69
70 #[error("Data decoding error: {0}")]
72 DecodingError(String),
73
74 #[error("Invalid data representation: {0}")]
76 InvalidDataRepresentation(String),
77
78 #[error("Invalid bitmap: {0}")]
80 InvalidBitmap(String),
81
82 #[error("Invalid level: type={level_type}, value={value}")]
84 InvalidLevel {
85 level_type: u8,
87 value: f64,
89 },
90
91 #[error("Invalid time specification: {0}")]
93 InvalidTime(String),
94
95 #[error("Truncated message: expected {expected} bytes, got {actual} bytes")]
97 TruncatedMessage {
98 expected: usize,
100 actual: usize,
102 },
103
104 #[error("Invalid end marker: expected '7777', found {0:?}")]
106 InvalidEndMarker(Vec<u8>),
107
108 #[error("Feature not implemented: {0}")]
110 NotImplemented(String),
111
112 #[error("Unsupported packing method: {0}")]
114 UnsupportedPacking(String),
115
116 #[error("Invalid bit operation: {0}")]
118 InvalidBitOperation(String),
119
120 #[error("Coordinate conversion error: {0}")]
122 CoordinateError(String),
123
124 #[error("Parse error: {0}")]
126 ParseError(String),
127
128 #[error("Value out of range: {0}")]
130 OutOfRange(String),
131
132 #[error("UTF-8 error: {0}")]
134 Utf8Error(#[from] std::str::Utf8Error),
135
136 #[error("Serialization error: {0}")]
138 SerializationError(String),
139
140 #[error("OxiGDAL integration error: {0}")]
142 IntegrationError(String),
143
144 #[error("Other error: {0}")]
146 Other(String),
147}
148
149impl GribError {
150 pub fn parse<S: Into<String>>(msg: S) -> Self {
152 Self::ParseError(msg.into())
153 }
154
155 pub fn decode<S: Into<String>>(msg: S) -> Self {
157 Self::DecodingError(msg.into())
158 }
159
160 pub fn grid<S: Into<String>>(msg: S) -> Self {
162 Self::InvalidGrid(msg.into())
163 }
164
165 pub fn data_repr<S: Into<String>>(msg: S) -> Self {
167 Self::InvalidDataRepresentation(msg.into())
168 }
169
170 pub fn not_impl<S: Into<String>>(feature: S) -> Self {
172 Self::NotImplemented(feature.into())
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_error_display() {
182 let err = GribError::InvalidHeader(vec![0x47, 0x52, 0x49, 0x41]);
183 assert!(err.to_string().contains("GRIB"));
184
185 let err = GribError::UnsupportedEdition(3);
186 assert!(err.to_string().contains("GRIB1 and GRIB2"));
187
188 let err = GribError::InvalidParameter {
189 discipline: 0,
190 category: 1,
191 number: 255,
192 };
193 assert!(err.to_string().contains("discipline=0"));
194 }
195
196 #[test]
197 fn test_error_constructors() {
198 let err = GribError::parse("test message");
199 assert!(matches!(err, GribError::ParseError(_)));
200
201 let err = GribError::decode("test decode");
202 assert!(matches!(err, GribError::DecodingError(_)));
203
204 let err = GribError::not_impl("complex packing");
205 assert!(matches!(err, GribError::NotImplemented(_)));
206 }
207}