use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("input size mismatch: expected {expected} samples, got {got}")]
InputSize {
expected: usize,
got: usize,
},
#[error("batch input size mismatch: segment {index} has {got} samples, expected {expected}")]
BatchInputSize {
index: usize,
expected: usize,
got: usize,
},
#[error("model detection failed: {reason}")]
ModelDetection {
reason: String,
},
#[error("label count mismatch: model expects {expected}, got {got}")]
LabelCount {
expected: usize,
got: usize,
},
#[error("model path required")]
ModelPathRequired,
#[error("labels required (provide path or vec)")]
LabelsRequired,
#[error("failed to load model: {0}")]
ModelLoad(#[from] ort::Error),
#[error("failed to load labels from {path}: {reason}")]
LabelLoad {
path: String,
reason: String,
},
#[error("failed to parse labels: {0}")]
LabelParse(String),
#[error("inference failed: {0}")]
Inference(String),
#[error("invalid coordinates: latitude: {latitude}, longitude: {longitude}, reason: {reason}")]
InvalidCoordinates {
latitude: f32,
longitude: f32,
reason: String,
},
#[error("invalid date: month: {month}, day: {day}, reason: {reason}")]
InvalidDate {
month: u32,
day: u32,
reason: String,
},
#[error("range filter inference failed: {0}")]
RangeFilterInference(String),
#[error("failed to initialize ONNX Runtime: {0}")]
RuntimeInit(String),
#[error("unsupported audio format: {reason}")]
AudioFormat {
reason: String,
},
#[error("failed to read audio file {path}: {reason}")]
AudioRead {
path: String,
reason: String,
},
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
#[test]
fn test_input_size_error_display() {
let err = Error::InputSize {
expected: 144_000,
got: 100_000,
};
assert_eq!(
err.to_string(),
"input size mismatch: expected 144000 samples, got 100000"
);
}
#[test]
fn test_batch_input_size_error_display() {
let err = Error::BatchInputSize {
index: 3,
expected: 144_000,
got: 50_000,
};
assert_eq!(
err.to_string(),
"batch input size mismatch: segment 3 has 50000 samples, expected 144000"
);
}
#[test]
fn test_model_detection_error_display() {
let err = Error::ModelDetection {
reason: "unsupported model".to_string(),
};
assert_eq!(err.to_string(), "model detection failed: unsupported model");
}
#[test]
fn test_label_count_error_display() {
let err = Error::LabelCount {
expected: 6522,
got: 1000,
};
assert_eq!(
err.to_string(),
"label count mismatch: model expects 6522, got 1000"
);
}
#[test]
fn test_audio_format_error_display() {
let err = Error::AudioFormat {
reason: "WAV must be mono".to_string(),
};
assert_eq!(
err.to_string(),
"unsupported audio format: WAV must be mono"
);
}
#[test]
fn test_audio_read_error_display() {
let err = Error::AudioRead {
path: "/path/to/file.wav".to_string(),
reason: "file not found".to_string(),
};
assert_eq!(
err.to_string(),
"failed to read audio file /path/to/file.wav: file not found"
);
}
#[test]
fn test_invalid_coordinates_error() {
let err = Error::InvalidCoordinates {
latitude: 95.0,
longitude: 200.0,
reason: "latitude out of range".to_string(),
};
assert!(err.to_string().contains("latitude: 95"));
assert!(err.to_string().contains("longitude: 200"));
}
#[test]
fn test_invalid_date_error() {
let err = Error::InvalidDate {
month: 13,
day: 32,
reason: "month out of range".to_string(),
};
assert!(err.to_string().contains("month: 13"));
assert!(err.to_string().contains("day: 32"));
assert!(err.to_string().contains("month out of range"));
}
#[test]
fn test_range_filter_inference_error() {
let err = Error::RangeFilterInference("model invoke failed".to_string());
assert_eq!(
err.to_string(),
"range filter inference failed: model invoke failed"
);
}
}