Skip to main content

gnss_time/
error.rs

1//! Error types for the `gnss-time` crate.
2//!
3//! This module defines the unified error type used across all fallible
4//! operations in the crate, including conversions, arithmetic, and
5//! time-scale transformations.
6//!
7//! The design follows a strict principle:
8//!
9//! - **No hidden failure modes** — all fallible operations return `Result`
10//! - **Explicit error context** — each variant describes a recoverable class of
11//!   failure
12//! - **`#[non_exhaustive]` for forward compatibility**
13
14use core::fmt::{self};
15
16/// Errors returned by fallible `gnss-time` operations.
17///
18/// `GnssTimeError` is used throughout the crate for arithmetic overflow,
19/// invalid inputs, and missing auxiliary data (e.g. leap seconds).
20///
21/// This type is intentionally `#[non_exhaustive]` to allow new error cases
22/// without breaking semver compatibility.
23///
24/// # Usage
25///
26/// ```rust
27/// use gnss_time::GnssTimeError;
28///
29/// fn example() -> Result<(), GnssTimeError> {
30///     Err(GnssTimeError::Overflow)
31/// }
32/// ```
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
34#[must_use = "errors must be handled; use `?` or `match` to inspect the failure"]
35#[non_exhaustive]
36pub enum GnssTimeError {
37    /// Arithmetic overflow occurred during nanosecond-based computations.
38    ///
39    /// This indicates that an operation exceeded the representable range of
40    /// the underlying `i64` nanosecond storage.
41    Overflow,
42
43    /// The provided input value is invalid for the requested operation.
44    ///
45    /// The attached string provides a short static description of the issue.
46    InvalidInput(&'static str),
47
48    /// The operation requires leap-second information that is not available.
49    ///
50    /// This is typically required for conversions between UTC-based and
51    /// atomic time scales (e.g. GPS ↔ UTC, GLONASS ↔ GPS).
52    LeapSecondsRequired,
53
54    /// The value lies outside the representable range of the timestamp.
55    ///
56    /// This occurs when a Unix timestamp is earlier than the UTC epoch
57    /// (1972-01-01) or when a conversion would result in a negative
58    /// nanosecond count.
59    OutOfRange,
60}
61
62impl fmt::Display for GnssTimeError {
63    fn fmt(
64        &self,
65        f: &mut fmt::Formatter<'_>,
66    ) -> fmt::Result {
67        match self {
68            GnssTimeError::Overflow => f.write_str("arithmetic overflow in nanoseconds"),
69            GnssTimeError::InvalidInput(msg) => {
70                write!(f, "invalid input: {msg}")
71            }
72            GnssTimeError::LeapSecondsRequired => f.write_str("leap-second data required"),
73            GnssTimeError::OutOfRange => f.write_str("timestamp is out of representable range"),
74        }
75    }
76}
77
78// `std::error::Error` impl behind the `std` feature gate.
79#[cfg(feature = "std")]
80impl std::error::Error for GnssTimeError {}
81
82// defmt support: embedded logging via probe-rs / defmt-rtt.
83#[cfg(feature = "defmt")]
84#[allow(clippy::match_same_arms)]
85impl defmt::Format for GnssTimeError {
86    fn format(
87        &self,
88        f: defmt::Formatter,
89    ) {
90        match self {
91            GnssTimeError::Overflow => {
92                defmt::write!(f, "arithmetic overflow in nanoseconds");
93            }
94            GnssTimeError::InvalidInput(msg) => {
95                defmt::write!(f, "invalid input: {}", msg);
96            }
97            GnssTimeError::LeapSecondsRequired => {
98                defmt::write!(f, "leap-second data required");
99            }
100            GnssTimeError::OutOfRange => {
101                defmt::write!(f, "timestamp is out of representable range");
102            }
103        }
104    }
105}