Skip to main content

iridium_units/
error.rs

1//! Error types for the iridium-units library.
2//!
3//! All fallible operations return [`UnitResult<T>`], which is an alias for
4//! `Result<T, UnitError>`. Errors include helpful context like unit names
5//! and, for unknown units, spelling suggestions.
6//!
7//! # Examples
8//!
9//! ```
10//! use iridium_units::prelude::*;
11//! use iridium_units::error::UnitError;
12//!
13//! // Incompatible conversion
14//! let mass = 1.0 * KG;
15//! let result = mass.to(M);
16//! assert!(matches!(result, Err(UnitError::DimensionMismatch { .. })));
17//!
18//! // Incompatible addition
19//! let distance = 10.0 * M;
20//! let time = 5.0 * S;
21//! let result = distance.checked_add(&time);
22//! assert!(matches!(result, Err(UnitError::IncompatibleDimensions { .. })));
23//!
24//! // Unknown unit with suggestion
25//! let result = parse_unit("metrs");
26//! if let Err(UnitError::UnknownUnit { suggestions, .. }) = result {
27//!     assert!(!suggestions.is_empty());
28//! }
29//! ```
30
31use thiserror::Error;
32
33/// Errors that can occur during unit operations.
34#[derive(Error, Debug, Clone)]
35pub enum UnitError {
36    /// Attempted to convert between incompatible dimensions.
37    #[error("cannot convert between incompatible dimensions: {from} -> {to}")]
38    DimensionMismatch {
39        /// The source unit.
40        from: String,
41        /// The target unit.
42        to: String,
43    },
44
45    /// Attempted to add or subtract quantities with different dimensions.
46    #[error("cannot add/subtract quantities with different dimensions: {lhs} vs {rhs}")]
47    IncompatibleDimensions {
48        /// The left-hand side unit.
49        lhs: String,
50        /// The right-hand side unit.
51        rhs: String,
52    },
53
54    /// Unknown unit name in string parsing.
55    #[error("unknown unit: '{name}'{}",
56        if suggestions.is_empty() { String::new() }
57        else { format!(", did you mean '{}'?", suggestions.join("' or '")) }
58    )]
59    UnknownUnit {
60        /// The unrecognized unit name.
61        name: String,
62        /// Suggested similar unit names, if any.
63        suggestions: Vec<String>,
64    },
65
66    /// Failed to parse a unit string.
67    #[error("failed to parse unit string: {0}")]
68    ParseError(String),
69
70    /// No equivalency available for the requested conversion.
71    #[error("no equivalency found for conversion: {from} -> {to}")]
72    NoEquivalency {
73        /// The source unit, which may include additional context.
74        from: String,
75        /// The target unit.
76        to: String,
77    },
78
79    /// Attempted to get scalar value from non-dimensionless quantity.
80    #[error("cannot convert non-dimensionless quantity to scalar")]
81    NotDimensionless,
82
83    /// Invalid operation on logarithmic unit.
84    #[error("invalid operation on logarithmic unit: {0}")]
85    LogarithmicError(String),
86
87    /// Overflow in dimension exponent calculation.
88    #[error("overflow in dimension exponent calculation")]
89    DimensionOverflow,
90
91    /// Zero denominator in rational exponent.
92    #[error("zero denominator in rational exponent")]
93    ZeroDenominator,
94
95    /// Attempted to use a simple scale factor for offset unit conversion.
96    /// Use `Quantity::to()` instead of `Unit::conversion_factor()` for offset units.
97    #[error(
98        "cannot use simple scaling for offset units: {from} -> {to}, use Quantity::to() instead"
99    )]
100    OffsetConversion {
101        /// The source unit.
102        from: String,
103        /// The target unit.
104        to: String,
105    },
106
107    /// Invalid input for batch operation.
108    #[error("batch operation error: {0}")]
109    BatchError(String),
110}
111
112/// Result type alias for unit operations.
113pub type UnitResult<T> = Result<T, UnitError>;