rapidgeo_polyline/error.rs
1//! Error types for polyline operations.
2
3use std::fmt;
4
5/// Errors that can occur during polyline encoding or decoding operations.
6///
7/// These errors provide detailed information about what went wrong during
8/// polyline processing, including specific locations for parsing errors
9/// and descriptive messages for coordinate validation failures.
10#[derive(Debug, Clone, PartialEq)]
11pub enum PolylineError {
12 /// Invalid character found in polyline string.
13 ///
14 /// Polyline strings must contain only ASCII characters in the range 63-126 ('?' to '~').
15 /// This error includes the invalid character and its position in the string.
16 InvalidCharacter { character: char, position: usize },
17
18 /// Truncated or malformed polyline data.
19 ///
20 /// Occurs when the polyline string ends unexpectedly, such as having a latitude
21 /// delta without a corresponding longitude delta, or when the variable-length
22 /// encoding is incomplete.
23 TruncatedData,
24
25 /// Coordinate value overflow during encoding or decoding.
26 ///
27 /// Happens when coordinate calculations exceed the range of 64-bit integers,
28 /// typically with very high precision values or extreme coordinate differences.
29 CoordinateOverflow,
30
31 /// Invalid precision value.
32 ///
33 /// Precision must be between 1 and 11 inclusive. Higher precision values
34 /// provide more accuracy but may cause overflow with large coordinate values.
35 InvalidPrecision(u8),
36
37 /// Empty input where coordinates were expected.
38 ///
39 /// Currently unused - empty inputs are handled gracefully by returning
40 /// empty results rather than errors.
41 EmptyInput,
42
43 /// Invalid coordinate value.
44 ///
45 /// Occurs when coordinates are NaN, infinite, or outside reasonable
46 /// geographic bounds (±180° longitude, ±90° latitude).
47 InvalidCoordinate(String),
48}
49
50impl fmt::Display for PolylineError {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 match self {
53 PolylineError::InvalidCharacter {
54 character,
55 position,
56 } => {
57 write!(
58 f,
59 "Invalid character '{}' at position {}",
60 character, position
61 )
62 }
63 PolylineError::TruncatedData => {
64 write!(f, "Polyline data is truncated or malformed")
65 }
66 PolylineError::CoordinateOverflow => {
67 write!(f, "Coordinate value overflow during encoding or decoding")
68 }
69 PolylineError::InvalidPrecision(precision) => {
70 write!(
71 f,
72 "Invalid precision {}, must be between 1 and 11",
73 precision
74 )
75 }
76 PolylineError::EmptyInput => {
77 write!(f, "Empty input provided")
78 }
79 PolylineError::InvalidCoordinate(message) => {
80 write!(f, "Invalid coordinate: {}", message)
81 }
82 }
83 }
84}
85
86impl std::error::Error for PolylineError {}
87
88/// Result type for polyline operations.
89///
90/// This is a convenience type alias for `Result<T, PolylineError>` used
91/// throughout the crate. All public functions return this type to provide
92/// consistent error handling.
93///
94/// # Example
95///
96/// ```rust
97/// use rapidgeo_polyline::{encode, PolylineResult};
98/// use rapidgeo_distance::LngLat;
99///
100/// fn encode_route(coords: &[LngLat]) -> PolylineResult<String> {
101/// encode(coords, 5)
102/// }
103/// ```
104pub type PolylineResult<T> = Result<T, PolylineError>;
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn test_invalid_character_display() {
112 let err = PolylineError::InvalidCharacter {
113 character: '!',
114 position: 5,
115 };
116 assert_eq!(err.to_string(), "Invalid character '!' at position 5");
117 }
118
119 #[test]
120 fn test_truncated_data_display() {
121 let err = PolylineError::TruncatedData;
122 assert_eq!(err.to_string(), "Polyline data is truncated or malformed");
123 }
124
125 #[test]
126 fn test_coordinate_overflow_display() {
127 let err = PolylineError::CoordinateOverflow;
128 assert_eq!(
129 err.to_string(),
130 "Coordinate value overflow during encoding or decoding"
131 );
132 }
133
134 #[test]
135 fn test_invalid_precision_display() {
136 let err = PolylineError::InvalidPrecision(15);
137 assert_eq!(
138 err.to_string(),
139 "Invalid precision 15, must be between 1 and 11"
140 );
141 }
142
143 #[test]
144 fn test_empty_input_display() {
145 let err = PolylineError::EmptyInput;
146 assert_eq!(err.to_string(), "Empty input provided");
147 }
148
149 #[test]
150 fn test_invalid_coordinate_display() {
151 let err = PolylineError::InvalidCoordinate("NaN value".to_string());
152 assert_eq!(err.to_string(), "Invalid coordinate: NaN value");
153 }
154
155 #[test]
156 fn test_error_trait_implementation() {
157 let err = PolylineError::TruncatedData;
158 let _: &dyn std::error::Error = &err;
159 }
160}