dotloom_geometry/error.rs
1use thiserror::Error;
2
3/// Errors produced by geometry operations.
4///
5/// Geometry functions never panic on bad input; they return one of these explicit
6/// results instead (non-finite numbers, degenerate shapes, unsupported transforms, ...).
7#[derive(Debug, Clone, PartialEq, Error)]
8#[non_exhaustive]
9pub enum GeometryError {
10 /// An input coordinate or parameter was NaN or infinite.
11 #[error("non-finite value in {0}")]
12 NonFinite(&'static str),
13 /// The shape has no extent where one is required (zero-length segment, zero radius, ...).
14 #[error("degenerate geometry: {0}")]
15 Degenerate(&'static str),
16 /// The transform has a (near) zero determinant and cannot be inverted.
17 #[error("singular transform (determinant {determinant:e})")]
18 SingularTransform {
19 /// Determinant of the linear part.
20 determinant: f64,
21 },
22 /// The transform cannot be applied while keeping the shape's semantics
23 /// (for example a non-uniform scale applied to a circle).
24 #[error("unsupported transform for {shape}: {reason}")]
25 UnsupportedTransform {
26 /// Shape kind name.
27 shape: &'static str,
28 /// Human readable reason.
29 reason: &'static str,
30 },
31 /// The requested operation is not defined for this shape kind.
32 #[error("operation `{operation}` is not supported for {shape}")]
33 UnsupportedOperation {
34 /// Operation name.
35 operation: &'static str,
36 /// Shape kind name.
37 shape: &'static str,
38 },
39 /// No intersection or boundary was found where the operation needs one.
40 #[error("no boundary found: {0}")]
41 NoBoundary(&'static str),
42 /// A parameter is outside its valid range.
43 #[error("invalid argument: {0}")]
44 InvalidArgument(&'static str),
45 /// Two quantities with different physical dimensions were combined.
46 #[error("dimension mismatch: {left} vs {right}")]
47 DimensionMismatch {
48 /// Left operand dimension.
49 left: String,
50 /// Right operand dimension.
51 right: String,
52 },
53 /// A unit string could not be parsed.
54 #[error("unknown unit `{0}`")]
55 UnknownUnit(String),
56}
57
58/// Result alias for geometry operations.
59pub type GeoResult<T> = Result<T, GeometryError>;
60
61pub(crate) fn finite(v: f64, what: &'static str) -> GeoResult<f64> {
62 if v.is_finite() { Ok(v) } else { Err(GeometryError::NonFinite(what)) }
63}