Skip to main content

sphereql_core/
error.rs

1/// All errors that `sphereql-core` can surface.
2///
3/// `#[non_exhaustive]` — new variants can be added in minor releases.
4/// Match with a `_ => …` arm when handling exhaustively.
5#[derive(Debug, Clone, thiserror::Error)]
6#[non_exhaustive]
7pub enum SphereQlError {
8    #[error("invalid radius {0}: must be >= 0")]
9    InvalidRadius(f64),
10    #[error("invalid theta {0}: must be in [0, 2π)")]
11    InvalidTheta(f64),
12    #[error("invalid phi {0}: must be in [0, π]")]
13    InvalidPhi(f64),
14    #[error("invalid latitude {0}: must be in [-90, 90]")]
15    InvalidLatitude(f64),
16    #[error("invalid longitude {0}: must be in [-180, 180]")]
17    InvalidLongitude(f64),
18    #[error("invalid altitude {0}: must be >= 0")]
19    InvalidAltitude(f64),
20    #[error("invalid shell bounds: inner {inner} must be < outer {outer}")]
21    InvalidShellBounds { inner: f64, outer: f64 },
22    #[error("invalid band bounds: phi_min {phi_min} must be < phi_max {phi_max}")]
23    InvalidBandBounds { phi_min: f64, phi_max: f64 },
24    #[error("invalid cone: half_angle {0} must be in (0, π]")]
25    InvalidConeAngle(f64),
26    #[error("invalid cap: half_angle {0} must be in (0, π]")]
27    InvalidCapAngle(f64),
28    #[error(
29        "invalid wedge bounds: theta_min {theta_min} and theta_max {theta_max} must be in [0, 2π)"
30    )]
31    InvalidWedgeBounds { theta_min: f64, theta_max: f64 },
32    #[error("zero vector cannot be normalized")]
33    ZeroVector,
34    #[error("vector length mismatch: expected {expected}, got {actual}")]
35    DimensionMismatch { expected: usize, actual: usize },
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn error_messages_are_human_readable() {
44        assert!(
45            SphereQlError::InvalidRadius(-1.0)
46                .to_string()
47                .contains("-1")
48        );
49        assert!(
50            SphereQlError::DimensionMismatch {
51                expected: 3,
52                actual: 2
53            }
54            .to_string()
55            .contains("3")
56        );
57        assert!(
58            SphereQlError::InvalidShellBounds {
59                inner: 5.0,
60                outer: 1.0
61            }
62            .to_string()
63            .contains("5")
64        );
65    }
66
67    #[test]
68    fn zero_vector_error_formats() {
69        let msg = SphereQlError::ZeroVector.to_string();
70        assert!(!msg.is_empty());
71    }
72}