1use std::num::TryFromIntError;
2
3use num_enum::TryFromPrimitiveError;
4
5use crate::decoder::{
6 GeometryType, LogicalEncoding, LogicalTechnique, PhysicalEncoding, StreamType,
7};
8
9pub type MltResult<T> = Result<T, MltError>;
10pub(crate) type MltRefResult<'a, T> = Result<(&'a [u8], T), MltError>;
11
12#[derive(Debug, thiserror::Error)]
13#[non_exhaustive]
14pub enum MltError {
15 #[error("cannot decode {0} as {1}")]
16 DataWidthMismatch(&'static str, &'static str),
17 #[error("dictionary index {0} out of bounds (len={1})")]
18 DictIndexOutOfBounds(u32, usize),
19 #[error("duplicate value found where unique required")]
20 DuplicateValue,
21 #[error("Integer overflow")]
22 IntegerOverflow,
23 #[error("missing geometry column in feature table")]
24 MissingGeometry,
25 #[error("missing layer name")]
26 MissingLayerName,
27 #[error("invalid extent: {0}")]
28 InvalidExtent(u32),
29 #[error("missing property name")]
30 MissingPropertyName,
31 #[error("duplicate property name: {0}")]
32 DuplicatePropertyName(String),
33 #[error("feature property count mismatch: expected {expected}, got {actual}")]
34 PropertyLengthMismatch { expected: usize, actual: usize },
35 #[error("property {index} kind mismatch: expected {expected:?}, got {actual:?}")]
36 PropertyKindMismatch {
37 index: usize,
38 expected: crate::tile::PropKind,
39 actual: crate::tile::PropKind,
40 },
41 #[error("staged column {column} feature count mismatch: expected {expected}, got {actual}")]
42 StagedFeatureCountMismatch {
43 column: String,
44 expected: usize,
45 actual: usize,
46 },
47 #[error("missing string stream: {0}")]
48 MissingStringStream(&'static str),
49 #[error("multiple geometry columns found (only one allowed)")]
50 MultipleGeometryColumns,
51 #[error("multiple ID columns found (only one allowed)")]
52 MultipleIdColumns,
53 #[error("varint uses more bytes than necessary (non-canonical encoding)")]
54 NonCanonicalVarInt,
55 #[error("{0} is not decoded")]
56 NotDecoded(&'static str),
57 #[error("decoded data is not in encoded form")]
58 NotEncoded,
59 #[error("error parsing column type: code={0}")]
60 ParsingColumnType(u8),
61 #[error("error parsing v2 stream encoding byte: 0x{0:02X}")]
62 ParsingEncodingByte(u8),
63 #[cfg(feature = "unstable-v2")]
64 #[error("error parsing v2 geometry layout: code={0}")]
65 ParsingGeoLayout(u8),
66 #[cfg(feature = "unstable-v2")]
67 #[error("error parsing v2 layer layout: byte=0x{0:02X}")]
68 ParsingLayerLayout(u8),
69 #[error("error parsing logical technique: code={0}")]
70 ParsingLogicalTechnique(u8),
71 #[error("error parsing physical encoding: code={0}")]
72 ParsingPhysicalEncoding(u8),
73 #[error("error parsing stream type: code={0}")]
74 ParsingStreamType(u8),
75 #[error("found {0} bytes after the expected end of layer")]
76 TrailingLayerData(usize),
77 #[error("unexpected end of input (unable to take {0} bytes)")]
78 UnableToTake(u32),
79 #[error("unexpected stream type {0:?}")]
80 UnexpectedStreamType(StreamType),
81 #[error("unexpected stream type {0:?}, expected {1} for {2}")]
82 UnexpectedStreamType2(StreamType, &'static str, &'static str),
83 #[error("unsupported logical encoding {0:?} for {1}")]
84 UnsupportedLogicalEncoding(LogicalEncoding, &'static str),
85 #[error("invalid combination of logical encodings: {0:?} + {1:?}")]
86 InvalidLogicalEncodings(LogicalTechnique, LogicalTechnique),
87 #[error("layer has zero size")]
88 ZeroLayerSize,
89 #[error("The encoder used to optimise data is incompatible")]
90 BadEncoderDataCombination,
91 #[error("StagedLayer::encode_explicit requires Encoder.explicit to be Some(_)")]
92 MissingExplicitEncoder,
93
94 #[error("buffer underflow: needed {0} bytes, but only {1} remain")]
96 BufferUnderflow(u32, usize),
97 #[error("FastPFor decode failed: expected={0} got={1}")]
98 FastPforDecode(u32, usize),
99 #[error("invalid RLE run length (cannot convert to usize): value={0}")]
100 RleRunLenInvalid(i128),
101
102 #[error("geometry requires at least 1 stream, got 0")]
104 GeometryWithoutStreams,
105 #[error("FastPFor data byte length expected multiple of 4, got {0}")]
106 InvalidFastPforByteLength(usize),
107 #[error("vec2 delta stream size expected to be non-empty and multiple of 2, got {0}")]
108 InvalidPairStreamSize(usize),
109 #[error("decodable stream size expected {1}, got {0}")]
110 InvalidDecodingStreamSize(usize, usize),
111 #[error("IDs missing for encoding (expected Some IDs, got None)")]
112 IdsMissingForEncoding,
113 #[error("missing struct encoder for struct")]
114 MissingStructEncoderForStruct,
115 #[error("previous decode/parsing attempt failed")]
116 PriorParseFailure,
117 #[error("presence stream has {0} bits set but {1} values provided")]
118 PresenceValueCountMismatch(usize, usize),
119 #[error("need to encode before being able to write")]
120 NeedsEncodingBeforeWriting,
121 #[error("memory limit exceeded: limit={limit}, used={used}, requested={requested}")]
122 MemoryLimitExceeded {
123 limit: u32,
124 used: u32,
125 requested: u32,
126 },
127 #[error("not implemented: {0}")]
128 NotImplemented(&'static str),
129 #[error("unsupported property value and encoder combination: {0:?} + {1:?}")]
130 UnsupportedPropertyEncoderCombination(&'static str, &'static str),
131 #[error("mixed property types are not allowed in column {0} ({1})")]
132 MixedPropertyTypes(usize, String),
133 #[error("shared dictionary requires at least 2 streams, got {0}")]
134 SharedDictRequiresStreams(usize),
135 #[error("unsupported string stream count (expected between 2 and 5): {0}")]
136 UnsupportedStringStreamCount(usize),
137 #[error("Structs are not allowed to be optional")]
138 TriedToEncodeOptionalStruct,
139 #[error(
140 "encoding instruction count mismatch: expected {input_len} instructions for {input_len} properties, got {config_len}"
141 )]
142 EncodingInstructionCountMismatch { input_len: usize, config_len: usize },
143 #[error("struct child data streams expected exactly 1 value, got {0}")]
144 UnexpectedStructChildCount(u32),
145 #[error("SharedDict stream count is {actual}, expected {expected}")]
147 InvalidSharedDictStreamCount { actual: u32, expected: u32 },
148 #[error("unsupported physical encoding: {0}")]
149 UnsupportedPhysicalEncoding(&'static str),
150 #[error("unsupported physical encoding: {0:?} for {1}")]
151 UnsupportedPhysicalEncodingForType(PhysicalEncoding, &'static str),
152 #[error(
153 "Extent {extent} cannot be encoded to morton due to morton allowing max. 16 bits, but {required_bits} would be required"
154 )]
155 VertexMortonNotCompatibleWithExtent { extent: u32, required_bits: u32 },
156 #[error("Morton stream uses {0} bits, but at most 16 bits are supported")]
157 InvalidMortonBits(u32),
158
159 #[error("MVT error: {0}")]
161 BadMvtGeometry(&'static str),
162 #[error("geometry[{0}]: index out of bounds")]
163 GeometryIndexOutOfBounds(usize),
164 #[error("geometry[{index}]: {field}[{idx}] out of bounds (len={len})")]
165 GeometryOutOfBounds {
166 index: usize,
167 field: &'static str,
168 idx: usize,
169 len: usize,
170 },
171 #[error("geometry[{index}]: vertex {vertex} out of bounds (count={count})")]
172 GeometryVertexOutOfBounds {
173 index: usize,
174 vertex: usize,
175 count: usize,
176 },
177 #[error("geometry[{0}]: {1} requires geometry_offsets")]
178 NoGeometryOffsets(usize, GeometryType),
179 #[error("geometry[{0}]: {1} requires part_offsets")]
180 NoPartOffsets(usize, GeometryType),
181 #[error("geometry[{0}]: {1} requires ring_offsets")]
182 NoRingOffsets(usize, GeometryType),
183 #[error("geometry[{0}]: unexpected offset combination for {1}")]
184 UnexpectedOffsetCombination(usize, GeometryType),
185
186 #[error("FastPFor error: {0}")]
187 FastPfor(#[from] fastpfor::FastPForError),
188 #[error(transparent)]
189 Io(#[from] std::io::Error),
190 #[error("Serde JSON error: {0}")]
191 SerdeJsonError(#[from] serde_json::Error),
192 #[error("integer conversion error: {0}")]
193 TryFromIntError(#[from] TryFromIntError),
194 #[error("num_enum conversion error: {0}")]
195 TryFromPrimitive(#[from] TryFromPrimitiveError<GeometryType>),
196 #[error("UTF-8 decode error: {0}")]
197 Utf8(#[from] std::str::Utf8Error),
198 #[error("UTF-8 decode error: {0}")]
199 FromUtf8(#[from] std::string::FromUtf8Error),
200 #[error("MVT error: {0}")]
201 Mvt(#[from] fast_mvt::MvtError),
202 #[error("MVT JSON value error: {0}")]
203 MvtJsonValue(#[from] fast_mvt::MvtJsonValueError),
204}
205
206impl From<MltError> for std::io::Error {
207 fn from(value: MltError) -> Self {
208 match value {
209 MltError::Io(e) => e,
210 other => Self::other(other),
211 }
212 }
213}
214
215pub(crate) trait AsMltError<T> {
216 fn or_overflow(&self) -> MltResult<T>;
217}
218
219impl<T: Copy> AsMltError<T> for Option<T> {
220 #[inline]
221 fn or_overflow(&self) -> MltResult<T> {
222 self.ok_or(MltError::IntegerOverflow)
223 }
224}
225
226impl AsMltError<u32> for Result<u32, TryFromIntError> {
227 #[inline]
228 fn or_overflow(&self) -> MltResult<u32> {
229 self.map_err(|_| MltError::IntegerOverflow)
230 }
231}
232
233#[inline]
234pub(crate) fn fail_if_invalid_stream_size(actual: usize, expected: usize) -> MltResult<()> {
235 if actual == expected {
236 Ok(())
237 } else {
238 Err(MltError::InvalidDecodingStreamSize(actual, expected))
239 }
240}