egml_core/error.rs
1use crate::model::base::Id;
2use thiserror::Error;
3
4/// Errors returned by `egml-core` operations.
5#[derive(Error, Debug, Eq, PartialEq, Hash, Clone)]
6pub enum Error {
7 /// Returned when a floating-point coordinate is not finite (NaN or ±infinity).
8 ///
9 /// The inner string names the offending coordinate component: `"x"`, `"y"`, or `"z"`.
10 /// GML requires all coordinate values in a `DirectPosition` to be real numbers
11 /// (ISO 19136 §9.4 `DirectPositionType`).
12 #[error(
13 "coordinate '{0}' has a non-finite value (NaN or ±infinity); all GML coordinate values must be real numbers (ISO 19136 §9.4)"
14 )]
15 NonFiniteCoordinate(&'static str),
16
17 /// Returned when a collection has fewer elements than the minimum required by
18 /// the GML geometry constraint.
19 ///
20 /// The inner string is a human-readable description of the violated constraint,
21 /// e.g. `"LinearRing requires at least 3 positions (ISO 19136 §10.5.12)"`.
22 #[error(
23 "{geometry} requires at least {minimum} elements ({spec:?}) [id={id:?}] [message={message:?}]"
24 )]
25 TooFewElements {
26 geometry: &'static str,
27 minimum: usize,
28 spec: Option<&'static str>,
29 id: Option<Id>,
30 message: Option<String>,
31 },
32
33 /// Returned when a collection contains a number of elements that is not
34 /// accepted by the operation (e.g. a `Triangle` not given exactly 3 points).
35 ///
36 /// The inner string describes which collection or argument was invalid.
37 #[error("invalid number of elements: {0}")]
38 WrongElementCount(&'static str),
39
40 /// Returned when an operation requires a non-empty input but received an empty one.
41 ///
42 /// The inner string names the offending parameter or context (e.g. `"solid"`,
43 /// `"multi curve"`).
44 #[error("'{0}' must not be empty")]
45 EmptyCollection(&'static str),
46
47 /// Returned when a geometry contains two identical positions where all positions
48 /// must be distinct (e.g. all three vertices of a [`Triangle`](crate::model::geometry::primitives::Triangle)
49 /// must be different, per ISO 19136 §10.5.9).
50 #[error(
51 "geometry contains two identical positions; all positions must be distinct (ISO 19136 §10.5.9)"
52 )]
53 IdenticalPositions,
54
55 /// Returned when adjacent positions in a sequence are equal and the geometry type
56 /// requires all consecutive positions to differ.
57 ///
58 /// Applies to [`LinearRing`](crate::model::geometry::primitives::LinearRing)
59 /// (ISO 19136 §10.5.12) and [`LineString`](crate::model::geometry::primitives::LineString)
60 /// (ISO 19136 §10.4.4).
61 #[error(
62 "sequence contains adjacent duplicate positions; consecutive coordinates must be distinct (ISO 19136 §10.4.3)"
63 )]
64 AdjacentDuplicatePositions,
65
66 /// Returned when the first and last position of a ring are equal.
67 ///
68 /// A `gml:LinearRing` is implicitly closed: the geometry engine connects the
69 /// last position back to the first automatically. An explicit repeated closing
70 /// vertex is therefore redundant and invalid (ISO 19136 §10.5.12).
71 #[error(
72 "linear ring has matching first and last positions; gml:LinearRing is implicitly closed and must not include an explicit closing vertex (ISO 19136 §10.5.12)"
73 )]
74 RepeatedClosingVertex,
75
76 /// Returned when an [`Envelope`](crate::model::geometry::Envelope) is constructed
77 /// with a lower corner that is strictly greater than the upper corner in one or
78 /// more coordinate components.
79 ///
80 /// The inner string names the offending component (`"x"`, `"y"`, or `"z"`).
81 /// ISO 19136 §10.1.4 requires `lowerCorner ≤ upperCorner` in every component.
82 #[error(
83 "envelope lowerCorner.{0} exceeds upperCorner.{0}; each component of lowerCorner must be ≤ the corresponding upperCorner component (ISO 19136 §10.1.4)"
84 )]
85 InvalidEnvelopeBounds(&'static str),
86
87 /// Returned when the earcut polygon triangulation algorithm produces no triangles.
88 ///
89 /// The inner string provides additional context about the failure (e.g. which
90 /// polygon or patch could not be decomposed).
91 #[error("polygon triangulation (earcut) failed: {0}")]
92 TriangulationFailed(&'static str),
93}