Skip to content

Commit c098063

Browse files
mpiannucciopencode
andcommitted
Improve error handling in DAS attribute parsing
- Add InvalidAttributeValue error variant for better error reporting - Replace unwrap() calls with proper error propagation using nom's error system - Convert parsing errors to appropriate nom error kinds (Digit, Float) - Update tests to return Result types instead of panicking - Add comprehensive test for invalid attribute value handling - All 42 tests passing with robust error handling 🤖 Generated with [opencode](https://opencode.ai) Co-Authored-By: opencode <noreply@opencode.ai>
1 parent 86ab804 commit c098063

File tree

2 files changed

+66
-15
lines changed

2 files changed

+66
-15
lines changed

src/das.rs

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,41 @@ impl DasAttribute {
3434
let (input, _) = tag(";")(input)?;
3535

3636
let value = match data_type {
37-
DataType::Byte => DataValue::Byte(raw_value.parse::<i8>().unwrap()),
38-
DataType::Int16 => DataValue::Int16(raw_value.parse::<i16>().unwrap()),
39-
DataType::UInt16 => DataValue::UInt16(raw_value.parse::<u16>().unwrap()),
40-
DataType::Int32 => DataValue::Int32(raw_value.parse::<i32>().unwrap()),
41-
DataType::UInt32 => DataValue::UInt32(raw_value.parse::<u32>().unwrap()),
42-
DataType::Float32 => DataValue::Float32(raw_value.parse::<f32>().unwrap()),
43-
DataType::Float64 => DataValue::Float64(raw_value.parse::<f64>().unwrap()),
37+
DataType::Byte => {
38+
let parsed = raw_value.parse::<i8>()
39+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit)))?;
40+
DataValue::Byte(parsed)
41+
}
42+
DataType::Int16 => {
43+
let parsed = raw_value.parse::<i16>()
44+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit)))?;
45+
DataValue::Int16(parsed)
46+
}
47+
DataType::UInt16 => {
48+
let parsed = raw_value.parse::<u16>()
49+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit)))?;
50+
DataValue::UInt16(parsed)
51+
}
52+
DataType::Int32 => {
53+
let parsed = raw_value.parse::<i32>()
54+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit)))?;
55+
DataValue::Int32(parsed)
56+
}
57+
DataType::UInt32 => {
58+
let parsed = raw_value.parse::<u32>()
59+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Digit)))?;
60+
DataValue::UInt32(parsed)
61+
}
62+
DataType::Float32 => {
63+
let parsed = raw_value.parse::<f32>()
64+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Float)))?;
65+
DataValue::Float32(parsed)
66+
}
67+
DataType::Float64 => {
68+
let parsed = raw_value.parse::<f64>()
69+
.map_err(|_| nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Float)))?;
70+
DataValue::Float64(parsed)
71+
}
4472
DataType::String => DataValue::String(raw_value.replace("\"", "")),
4573
DataType::URL => DataValue::URL(raw_value.replace("\"", "")),
4674
};
@@ -131,9 +159,9 @@ mod tests {
131159
use super::{parse_das_attributes, parse_das_variable, DasAttribute};
132160

133161
#[test]
134-
fn parse_attribute() {
162+
fn parse_attribute() -> Result<(), Box<dyn std::error::Error>> {
135163
let input = r#"String long_name "Longitude";"#;
136-
let (_, string_value) = DasAttribute::parse(input).unwrap();
164+
let (_, string_value) = DasAttribute::parse(input)?;
137165
assert_eq!(string_value.data_type, DataType::String);
138166
assert_eq!(string_value.name, "long_name");
139167
let value = if let DataValue::String(s) = string_value.value {
@@ -144,7 +172,7 @@ mod tests {
144172
assert_eq!(value, "Longitude");
145173

146174
let input = "Int32 _FillValue 999;";
147-
let (_, int_value) = DasAttribute::parse(input).unwrap();
175+
let (_, int_value) = DasAttribute::parse(input)?;
148176
assert_eq!(int_value.data_type, DataType::Int32);
149177
assert_eq!(int_value.name, "_FillValue");
150178
let value = if let DataValue::Int32(i) = int_value.value {
@@ -155,7 +183,7 @@ mod tests {
155183
assert_eq!(value, 999);
156184

157185
let input = "Float32 _FillValue 999.0;";
158-
let (_, float_value) = DasAttribute::parse(input).unwrap();
186+
let (_, float_value) = DasAttribute::parse(input)?;
159187
assert_eq!(float_value.data_type, DataType::Float32);
160188
assert_eq!(float_value.name, "_FillValue");
161189
let value = if let DataValue::Float32(f) = float_value.value {
@@ -164,10 +192,11 @@ mod tests {
164192
0.0
165193
};
166194
assert!((value - 999.0).abs() < 0.0001);
195+
Ok(())
167196
}
168197

169198
#[test]
170-
fn parse_variable() {
199+
fn parse_variable() -> Result<(), Box<dyn std::error::Error>> {
171200
let input = r#" spectral_wave_density {
172201
String long_name "Spectral Wave Density";
173202
String short_name "swden";
@@ -176,7 +205,7 @@ mod tests {
176205
Float32 _FillValue 999.0;
177206
}"#;
178207

179-
let (_, (name, attrs)) = parse_das_variable(input).unwrap();
208+
let (_, (name, attrs)) = parse_das_variable(input)?;
180209
assert_eq!(name, "spectral_wave_density");
181210
assert_eq!(attrs.len(), 5);
182211
assert_eq!(attrs["long_name"].data_type, DataType::String);
@@ -192,10 +221,11 @@ mod tests {
192221
} else {
193222
false
194223
});
224+
Ok(())
195225
}
196226

197227
#[test]
198-
fn parse_das() {
228+
fn parse_das() -> Result<(), Box<dyn std::error::Error>> {
199229
let input = r#"Attributes {
200230
time {
201231
String long_name "Epoch Time";
@@ -210,10 +240,29 @@ mod tests {
210240
String units "Hz";
211241
}
212242
}"#;
213-
let attrs = parse_das_attributes(input).unwrap();
243+
let attrs = parse_das_attributes(input)?;
214244

215245
assert_eq!(attrs.len(), 2);
216246
assert!(attrs.contains_key("time"));
217247
assert!(attrs.contains_key("frequency"));
248+
Ok(())
249+
}
250+
251+
#[test]
252+
fn parse_invalid_attribute_values() {
253+
// Test invalid integer
254+
let input = "Int32 _FillValue not_a_number;";
255+
let result = DasAttribute::parse(input);
256+
assert!(result.is_err());
257+
258+
// Test invalid float
259+
let input = "Float32 _FillValue invalid_float;";
260+
let result = DasAttribute::parse(input);
261+
assert!(result.is_err());
262+
263+
// Test invalid byte
264+
let input = "Byte quality_flag 999;"; // Out of range for i8
265+
let result = DasAttribute::parse(input);
266+
assert!(result.is_err());
218267
}
219268
}

src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub enum Error {
88
ParseError,
99
#[error("Invalid Typecast")]
1010
InvalidTypecast,
11+
#[error("Invalid Attribute Value: {0}")]
12+
InvalidAttributeValue(String),
1113
#[error("Not Implemented")]
1214
NotImplemented,
1315
}

0 commit comments

Comments
 (0)