sounding_validate/
error.rs

1//! Errors for the sounding-validate crate.
2use std::error::Error;
3use std::fmt;
4
5/// Validation errors.
6#[derive(Clone, Copy, Debug, PartialEq)]
7pub enum ValidationError {
8    /// Sounding did not have a profile for pressure.
9    NoPressureProfile,
10    /// One of the profiles had a vector length that did not match the length of the pressure
11    /// profile vector. This is required because pressure is the vertical coordinate. The string is
12    /// the name of the profile, the first `usize` is the length of that profile, and the second
13    /// `usize` is the length it should have been.
14    InvalidVectorLength(&'static str, usize, usize),
15    /// Pressure not decreasing with height. This also checks that geopotential increases
16    /// "with height". It assumes the vectors are sorted with values from the lowest level to the
17    /// highest level above ground.
18    PressureNotDecreasingWithHeight,
19    /// Checks the required relationship between temperature and wet bulb.
20    TemperatureLessThanWetBulb(f64, f64),
21    /// Checks the required relationship between temperature and dew point.
22    TemperatureLessThanDewPoint(f64, f64),
23    /// Checks the required relationship between wet bulb and dew point.
24    WetBulbLessThanDewPoint(f64, f64),
25    /// Invalid negative value, such as speed which must be positive.
26    InvalidNegativeValue(&'static str, f64),
27    /// Invalid wind direction.
28    InvalidWindDirection(f64),
29}
30
31impl fmt::Display for ValidationError {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        use crate::ValidationError::*;
34
35        match self {
36            NoPressureProfile => write!(f, "missing pressure profile"),
37            InvalidVectorLength(_, _, _) => write!(f, "vectors do not match length"),
38            PressureNotDecreasingWithHeight => write!(f, "pressure not decreasing with height"),
39            TemperatureLessThanWetBulb(_, _) => write!(f, "temperature less than wet bulb"),
40            TemperatureLessThanDewPoint(_, _) => write!(f, "temperature less than dew point"),
41            WetBulbLessThanDewPoint(_, _) => write!(f, "wet bulb less than dew point"),
42            InvalidNegativeValue(msg, val) => {
43                write!(f, "invalid negative value: {} : {}", msg, val)
44            }
45            InvalidWindDirection(dir) => write!(f, "invalid wind direction: {}", dir),
46        }
47    }
48}
49
50impl Error for ValidationError {}
51
52/// Collection of validation errors.
53#[derive(Debug, Default)]
54pub struct ValidationErrors {
55    errors: Vec<ValidationError>,
56}
57
58impl ValidationErrors {
59    /// Create a new collection of errors.
60    pub fn new() -> Self {
61        ValidationErrors { errors: vec![] }
62    }
63
64    /// Get the interior list of errors.
65    pub fn into_inner(self) -> Vec<ValidationError> {
66        self.errors
67    }
68
69    /// Add an error to this list
70    pub fn push_error(&mut self, result: Result<(), ValidationError>) {
71        match result {
72            Ok(()) => {}
73            Err(err) => self.errors.push(err),
74        }
75    }
76
77    /// Check if there are any errors, if not return `Ok`, otherwise return `self`.
78    pub fn check_any(self) -> Result<(), ValidationErrors> {
79        if self.errors.is_empty() {
80            Ok(())
81        } else {
82            Err(self)
83        }
84    }
85}
86
87impl fmt::Display for ValidationErrors {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        writeln!(f, "\nValidation Errors")?;
90        for error in &self.errors {
91            writeln!(f, "     {}", error)?;
92        }
93
94        writeln!(f)
95    }
96}
97
98impl Error for ValidationErrors {}