1use std::num::TryFromIntError;
2
3use num_enum::TryFromPrimitiveError;
4
5use crate::decoder::{
6 GeometryType, LogicalCombination, LogicalEncoding, LogicalTechnique, PhysicalEncoding,
7 StreamType, ValueKind,
8};
9
10pub type MltResult<T> = Result<T, MltError>;
11pub(crate) type MltRefResult<'a, T> = Result<(&'a [u8], T), MltError>;
12
13#[derive(Debug, thiserror::Error)]
14#[non_exhaustive]
15pub enum MltError {
16 #[error("cannot decode {0} as {1}")]
17 DataWidthMismatch(&'static str, &'static str),
18 #[error("dictionary index {0} out of bounds (len={1})")]
19 DictIndexOutOfBounds(u32, usize),
20 #[error("duplicate value found where unique required")]
21 DuplicateValue,
22 #[error("Integer overflow")]
23 IntegerOverflow,
24 #[error("missing geometry column in feature table")]
25 MissingGeometry,
26 #[error("missing layer name")]
27 MissingLayerName,
28 #[error("invalid extent: {0}")]
29 InvalidExtent(u32),
30 #[error("missing property name")]
31 MissingPropertyName,
32 #[error("duplicate column name {name}: the {role} column repeats the {taken_by} column")]
33 DuplicateColumnName {
34 name: String,
35 role: crate::tile::ColumnRole,
36 taken_by: crate::tile::ColumnRole,
37 },
38 #[error("feature property count mismatch: expected {expected}, got {actual}")]
39 PropertyLengthMismatch { expected: usize, actual: usize },
40 #[error("property {index} kind mismatch: expected {expected:?}, got {actual:?}")]
41 PropertyKindMismatch {
42 index: usize,
43 expected: crate::tile::PropKind,
44 actual: crate::tile::PropKind,
45 },
46 #[error("staged column {column} feature count mismatch: expected {expected}, got {actual}")]
47 StagedFeatureCountMismatch {
48 column: String,
49 expected: usize,
50 actual: usize,
51 },
52 #[error("missing string stream: {0}")]
53 MissingStringStream(&'static str),
54 #[error("multiple geometry columns found (only one allowed)")]
55 MultipleGeometryColumns,
56 #[error("multiple ID columns found (only one allowed)")]
57 MultipleIdColumns,
58 #[error("varint uses more bytes than necessary (non-canonical encoding)")]
59 NonCanonicalVarInt,
60 #[error("{0} is not decoded")]
61 NotDecoded(&'static str),
62 #[error("decoded data is not in encoded form")]
63 NotEncoded,
64 #[error("error parsing column type: code={0}")]
65 ParsingColumnType(u8),
66 #[error("error parsing v2 stream encoding byte: 0x{0:02X}")]
67 ParsingEncodingByte(u8),
68 #[cfg(feature = "unstable-v2")]
69 #[error(
70 "a v2 {0:?} stream carries no value count, and nothing in its context implies one: encoding byte 0x{1:02X}"
71 )]
72 StreamWithoutCount(StreamType, u8),
73 #[cfg(feature = "unstable-v2")]
74 #[error("error parsing v2 geometry layout: code={0}")]
75 ParsingGeoLayout(u8),
76 #[cfg(feature = "unstable-v2")]
77 #[error("error parsing v2 layer header byte: 0x{0:02X}")]
78 ParsingLayerHeader02(u8),
79 #[cfg(feature = "unstable-v2")]
80 #[error("error parsing v2 layer layout byte: 0x{0:02X}")]
81 ParsingLayerLayout02(u8),
82 #[cfg(feature = "unstable-v2")]
83 #[error("v2 extent {0} is not a power of two in 64..=2097152")]
84 UnsupportedExtent02(u32),
85 #[cfg(feature = "unstable-v2")]
86 #[error(
87 "v2 geometry layout {0} gives no per-feature vertex count, so it cannot carry m-values"
88 )]
89 MValuesNeedVertexCounts(&'static str),
90 #[cfg(feature = "unstable-v2")]
91 #[error("the v2 layer header byte claims an m-value section, but it holds no columns")]
92 EmptyMValueSection,
93 #[cfg(feature = "unstable-v2")]
94 #[error(
95 "m-value column {name} has no implied count, so its leading stream must write one: encoding byte 0x{byte:02X}"
96 )]
97 MValueImplicitCount { name: String, byte: u8 },
98 #[cfg(feature = "unstable-v2")]
99 #[error(
100 "m-value column {name} holds {actual} values, but its features have {expected} vertices"
101 )]
102 MValueColumnLengthMismatch {
103 name: String,
104 expected: usize,
105 actual: usize,
106 },
107 #[cfg(feature = "unstable-v2")]
108 #[error(
109 "m-value column {name} holds {actual} values, so a feature's run of {count} at offset {start} is out of range"
110 )]
111 MValueRunOutOfRange {
112 name: String,
113 start: usize,
114 count: usize,
115 actual: usize,
116 },
117 #[cfg(feature = "unstable-v2")]
118 #[error("a feature carries {actual} m-value columns, but the layer has {expected}")]
119 MValueColumnCountMismatch { expected: usize, actual: usize },
120 #[cfg(feature = "unstable-v2")]
121 #[error("m-value key {index} belongs to another layer: this feature has {columns} columns")]
122 UnknownMValueKey { index: usize, columns: usize },
123 #[cfg(feature = "unstable-v2")]
124 #[error("m-value {index} kind mismatch: expected {expected:?}, got {actual:?}")]
125 MValueKindMismatch {
126 index: usize,
127 expected: crate::tile::PropKind,
128 actual: crate::tile::PropKind,
129 },
130 #[cfg(feature = "unstable-v2")]
131 #[error("m-value {index} holds {actual} values, but the feature has {expected} vertices")]
132 MValueVertexCountMismatch {
133 index: usize,
134 expected: usize,
135 actual: usize,
136 },
137 #[cfg(feature = "unstable-v2")]
138 #[error("m-values are a v2 feature, so layer {0} cannot be written as v1")]
139 MValuesNeedV2(String),
140 #[cfg(feature = "unstable-v2")]
141 #[error("nested properties are a v2 feature, so layer {0} cannot be written as v1")]
142 NestedNeedsV2(String),
143 #[cfg(feature = "unstable-v2")]
144 #[error("duplicate field name in a struct node: {0}")]
145 DuplicateFieldName(String),
146 #[cfg(feature = "unstable-v2")]
147 #[error("a struct node holds no fields")]
148 EmptyStructNode,
149 #[cfg(feature = "unstable-v2")]
150 #[error("nested column {0} has a scalar root, which is an ordinary column")]
151 NestedRootIsLeaf(String),
152 #[cfg(feature = "unstable-v2")]
153 #[error("a nested column is {0} levels deep, more than the 8 the format allows")]
154 NestedTooDeep(usize),
155 #[cfg(feature = "unstable-v2")]
156 #[error("a nested lengths stream sums to {expected}, but the node below it holds {actual}")]
157 NestedCountMismatch { expected: u32, actual: u32 },
158 #[cfg(feature = "unstable-v2")]
159 #[error(
160 "nested node {name} has no implied count, so its leading stream must write one: encoding byte 0x{byte:02X}"
161 )]
162 NestedImplicitCount { name: String, byte: u8 },
163 #[cfg(feature = "unstable-v2")]
164 #[error("a feature carries {actual} nested columns, but the layer has {expected}")]
165 NestedColumnCountMismatch { expected: usize, actual: usize },
166 #[cfg(feature = "unstable-v2")]
167 #[error("nested key {index} belongs to another layer: this feature has {columns} columns")]
168 UnknownNestedKey { index: usize, columns: usize },
169 #[cfg(feature = "unstable-v2")]
170 #[error("nested column {index} ({name}) was given a value of another shape")]
171 NestedValueMismatch { index: usize, name: String },
172 #[cfg(feature = "unstable-v2")]
173 #[error("nested column {index} was given a value of another shape")]
174 NestedShapeMismatch { index: usize },
175 #[cfg(feature = "unstable-v2")]
176 #[error("nested column {name} runs over {expected} values, but its root holds {actual}")]
177 NestedRootCountMismatch {
178 name: String,
179 expected: u32,
180 actual: u32,
181 },
182 #[cfg(feature = "unstable-v2")]
183 #[error(
184 "nested node {name} must write its presence as a raw bitmap of one bit per value: encoding byte 0x{byte:02X}"
185 )]
186 NestedPresenceEncoding { name: String, byte: u8 },
187 #[cfg(feature = "unstable-v2")]
188 #[error("a nested lengths stream holds {len} lengths, so it has no row {row}")]
189 NestedRowOutOfRange { row: usize, len: usize },
190 #[cfg(feature = "unstable-v2")]
191 #[error("a nested map holds {len} keys, so it has no key for entry {entry}")]
192 NestedKeyOutOfRange { entry: usize, len: usize },
193 #[cfg(feature = "unstable-v2")]
194 #[error("a nested leaf holds {len} values, so it has no value at index {index}")]
195 NestedValueOutOfRange { index: usize, len: usize },
196 #[cfg(feature = "unstable-v2")]
197 #[error("a row-shape table of {bits} bits does not divide into shapes of {keys} keys")]
198 NestedRowShapeTableSize { bits: usize, keys: usize },
199 #[cfg(feature = "unstable-v2")]
200 #[error("a shape-coded nested node has {len} row shapes, so it has no shape {id}")]
201 NestedRowShapeOutOfRange { id: u32, len: usize },
202 #[cfg(feature = "unstable-v2")]
203 #[error("nested node {name} is shape-coded over {expected} rows, but holds {actual} shape ids")]
204 NestedRowShapeCount {
205 name: String,
206 expected: u32,
207 actual: u32,
208 },
209 #[cfg(feature = "unstable-v2")]
210 #[error(
211 "nested node {name} reads its presence from its parent's row shapes, so it stores none of its own"
212 )]
213 NestedRowShapeChildPresence { name: String },
214 #[cfg(feature = "unstable-v2")]
215 #[error("nested node {name} is a {kind}, which has no row shapes to read")]
216 NestedRowShapeUnsupported { name: String, kind: &'static str },
217 #[error("error parsing logical technique: code={0}")]
218 ParsingLogicalTechnique(u8),
219 #[error("error parsing physical encoding: code={0}")]
220 ParsingPhysicalEncoding(u8),
221 #[error("error parsing stream type: code={0}")]
222 ParsingStreamType(u8),
223 #[error("found {0} bytes after the expected end of layer")]
224 TrailingLayerData(usize),
225 #[error("unexpected end of input (unable to take {0} bytes)")]
226 UnableToTake(u32),
227 #[error("unexpected stream type {0:?}")]
228 UnexpectedStreamType(StreamType),
229 #[error("unexpected stream type {0:?}, expected {1} for {2}")]
230 UnexpectedStreamType2(StreamType, &'static str, &'static str),
231 #[error("unsupported logical encoding {0:?} for {1}")]
232 UnsupportedLogicalEncoding(LogicalEncoding, &'static str),
233 #[error("invalid combination of logical encodings: {0:?} + {1:?}")]
234 InvalidLogicalEncodings(LogicalTechnique, LogicalTechnique),
235 #[error("logical encoding {0:?} is not one a {1:?} stream has")]
236 LogicalEncodingNotInKind(LogicalCombination, ValueKind),
237 #[error("layer has zero size")]
238 ZeroLayerSize,
239 #[error("bit-packed stream width {0} is outside 1..=32")]
240 #[cfg(feature = "unstable-v2")]
241 ParsingBitWidth(u32),
242 #[error("The encoder used to optimise data is incompatible")]
243 BadEncoderDataCombination,
244 #[error("StagedLayer::encode_explicit requires Encoder.explicit to be Some(_)")]
245 MissingExplicitEncoder,
246
247 #[error("buffer underflow: needed {0} bytes, but only {1} remain")]
249 BufferUnderflow(u32, usize),
250 #[error("FastPFor decode failed: expected={0} got={1}")]
251 FastPforDecode(u32, usize),
252 #[error("invalid RLE run length (cannot convert to usize): value={0}")]
253 RleRunLenInvalid(i128),
254
255 #[error("geometry requires at least 1 stream, got 0")]
257 GeometryWithoutStreams,
258 #[error("FastPFor data byte length expected multiple of 4, got {0}")]
259 InvalidFastPforByteLength(usize),
260 #[error("vec2 delta stream size expected to be non-empty and multiple of 2, got {0}")]
261 InvalidPairStreamSize(usize),
262 #[error("decodable stream size expected {1}, got {0}")]
263 InvalidDecodingStreamSize(usize, usize),
264 #[error("IDs missing for encoding (expected Some IDs, got None)")]
265 IdsMissingForEncoding,
266 #[error("missing struct encoder for struct")]
267 MissingStructEncoderForStruct,
268 #[error("previous decode/parsing attempt failed")]
269 PriorParseFailure,
270 #[error("FSST-compressed data is malformed: {0}")]
271 MalformedFsst(&'static str),
272 #[cfg(feature = "unstable-v2")]
273 #[error("dictionary code {0} is out of range for a dictionary of {1} values")]
274 DictionaryCodeOutOfRange(u32, usize),
275 #[cfg(feature = "unstable-v2")]
276 #[error(
277 "front-coded lengths stream holds a prefix and a suffix length per entry, so its {0} values cannot be split in two"
278 )]
279 FrontCodedOddLengthCount(usize),
280 #[cfg(feature = "unstable-v2")]
281 #[error(
282 "front-coded entry {index} shares {shared} bytes with a predecessor of only {available}"
283 )]
284 FrontCodedPrefixTooLong {
285 index: usize,
286 shared: usize,
287 available: usize,
288 },
289 #[cfg(feature = "unstable-v2")]
290 #[error(
291 "front-coded entry {index} needs {needed} suffix bytes, but {available} remain in the blob"
292 )]
293 FrontCodedSuffixOutOfBounds {
294 index: usize,
295 needed: usize,
296 available: usize,
297 },
298 #[cfg(feature = "unstable-v2")]
299 #[error("front-coded dictionary leaves {0} suffix bytes after its last entry")]
300 FrontCodedTrailingSuffixBytes(usize),
301 #[cfg(feature = "unstable-v2")]
302 #[error("no ALP parameters return this float column bit-for-bit")]
303 NoAlpParameters,
304 #[error("invalid ALP parameters: e={0}, f={1}")]
305 InvalidAlpParams(u8, u8),
306 #[error("presence stream has {0} bits set but {1} values provided")]
307 PresenceValueCountMismatch(usize, usize),
308 #[error("need to encode before being able to write")]
309 NeedsEncodingBeforeWriting,
310 #[error("memory limit exceeded: limit={limit}, used={used}, requested={requested}")]
311 MemoryLimitExceeded {
312 limit: u32,
313 used: u32,
314 requested: u32,
315 },
316 #[error("not implemented: {0}")]
317 NotImplemented(&'static str),
318 #[error("unsupported property value and encoder combination: {0:?} + {1:?}")]
319 UnsupportedPropertyEncoderCombination(&'static str, &'static str),
320 #[error("mixed property types are not allowed in column {0} ({1})")]
321 MixedPropertyTypes(usize, String),
322 #[error("shared dictionary requires at least 2 streams, got {0}")]
323 SharedDictRequiresStreams(usize),
324 #[error("unsupported string stream count (expected between 2 and 5): {0}")]
325 UnsupportedStringStreamCount(usize),
326 #[error("Structs are not allowed to be optional")]
327 TriedToEncodeOptionalStruct,
328 #[error(
329 "encoding instruction count mismatch: expected {input_len} instructions for {input_len} properties, got {config_len}"
330 )]
331 EncodingInstructionCountMismatch { input_len: usize, config_len: usize },
332 #[error("struct child data streams expected exactly 1 value, got {0}")]
333 UnexpectedStructChildCount(u32),
334 #[error("SharedDict stream count is {actual}, expected {expected}")]
336 InvalidSharedDictStreamCount { actual: u32, expected: u32 },
337 #[error("unsupported physical encoding: {0}")]
338 UnsupportedPhysicalEncoding(&'static str),
339 #[error("unsupported physical encoding: {0:?} for {1}")]
340 UnsupportedPhysicalEncodingForType(PhysicalEncoding, &'static str),
341 #[error(
342 "Extent {extent} cannot be encoded to morton due to morton allowing max. 16 bits, but {required_bits} would be required"
343 )]
344 VertexMortonNotCompatibleWithExtent { extent: u32, required_bits: u32 },
345 #[error("Morton stream uses {0} bits, but at most 16 bits are supported")]
346 InvalidMortonBits(u32),
347
348 #[error("MVT error: {0}")]
350 BadMvtGeometry(&'static str),
351 #[error("geometry[{0}]: index out of bounds")]
352 GeometryIndexOutOfBounds(usize),
353 #[error("geometry[{index}]: {field}[{idx}] out of bounds (len={len})")]
354 GeometryOutOfBounds {
355 index: usize,
356 field: &'static str,
357 idx: usize,
358 len: usize,
359 },
360 #[error("geometry[{index}]: vertex {vertex} out of bounds (count={count})")]
361 GeometryVertexOutOfBounds {
362 index: usize,
363 vertex: usize,
364 count: usize,
365 },
366 #[error("geometry[{0}]: {1} requires geometry_offsets")]
367 NoGeometryOffsets(usize, GeometryType),
368 #[error("geometry[{0}]: {1} requires part_offsets")]
369 NoPartOffsets(usize, GeometryType),
370 #[error("geometry[{0}]: {1} requires ring_offsets")]
371 NoRingOffsets(usize, GeometryType),
372 #[error("geometry[{0}]: unexpected offset combination for {1}")]
373 UnexpectedOffsetCombination(usize, GeometryType),
374 #[error("geometry: ring lengths without part lengths")]
375 RingLengthsWithoutPartLengths,
376
377 #[error("FastPFor error: {0}")]
378 FastPfor(#[from] fastpfor::FastPForError),
379 #[error(transparent)]
380 Io(#[from] std::io::Error),
381 #[error("Serde JSON error: {0}")]
382 SerdeJsonError(#[from] serde_json::Error),
383 #[error("integer conversion error: {0}")]
384 TryFromIntError(#[from] TryFromIntError),
385 #[error("num_enum conversion error: {0}")]
386 TryFromPrimitive(#[from] TryFromPrimitiveError<GeometryType>),
387 #[error("UTF-8 decode error: {0}")]
388 Utf8(#[from] std::str::Utf8Error),
389 #[error("UTF-8 decode error: {0}")]
390 FromUtf8(#[from] std::string::FromUtf8Error),
391 #[error("MVT error: {0}")]
392 Mvt(#[from] fast_mvt::MvtError),
393 #[error("MVT JSON value error: {0}")]
394 MvtJsonValue(#[from] fast_mvt::MvtJsonValueError),
395}
396
397impl From<MltError> for std::io::Error {
398 fn from(value: MltError) -> Self {
399 if let MltError::Io(e) = value {
400 e
401 } else {
402 Self::other(value)
403 }
404 }
405}
406
407pub(crate) trait AsMltError<T> {
408 fn or_overflow(&self) -> MltResult<T>;
409}
410
411impl<T: Copy> AsMltError<T> for Option<T> {
412 #[inline]
413 fn or_overflow(&self) -> MltResult<T> {
414 self.ok_or(MltError::IntegerOverflow)
415 }
416}
417
418impl AsMltError<u32> for Result<u32, TryFromIntError> {
419 #[inline]
420 fn or_overflow(&self) -> MltResult<u32> {
421 self.map_err(|_| MltError::IntegerOverflow)
422 }
423}
424
425#[inline]
426pub(crate) fn fail_if_invalid_stream_size(actual: usize, expected: usize) -> MltResult<()> {
427 if actual == expected {
428 Ok(())
429 } else {
430 Err(MltError::InvalidDecodingStreamSize(actual, expected))
431 }
432}