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>;