1use std::convert::Infallible;
2use std::num::TryFromIntError;
3
4use num_enum::TryFromPrimitiveError;
5
6use crate::utils::AsUsize;
7use crate::v01::{GeometryType, LogicalEncoding, LogicalTechnique, PhysicalEncoding, StreamType};
8
9pub type MltResult<T> = Result<T, MltError>;
10pub 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 string stream: {0}")]
26 MissingStringStream(&'static str),
27 #[error("multiple geometry columns found (only one allowed)")]
28 MultipleGeometryColumns,
29 #[error("multiple ID columns found (only one allowed)")]
30 MultipleIdColumns,
31 #[error("varint uses more bytes than necessary (non-canonical encoding)")]
32 NonCanonicalVarInt,
33 #[error("{0} is not decoded")]
34 NotDecoded(&'static str),
35 #[error("decoded data is not in encoded form")]
36 NotEncoded,
37 #[error("error parsing column type: code={0}")]
38 ParsingColumnType(u8),
39 #[error("error parsing logical technique: code={0}")]
40 ParsingLogicalTechnique(u8),
41 #[error("error parsing physical encoding: code={0}")]
42 ParsingPhysicalEncoding(u8),
43 #[error("error parsing stream type: code={0}")]
44 ParsingStreamType(u8),
45 #[error("found {0} bytes after the expected end of layer")]
46 TrailingLayerData(usize),
47 #[error("unexpected end of input (unable to take {0} bytes)")]
48 UnableToTake(u32),
49 #[error("unexpected stream type {0:?}")]
50 UnexpectedStreamType(StreamType),
51 #[error("unexpected stream type {0:?}, expected {1} for {2}")]
52 UnexpectedStreamType2(StreamType, &'static str, &'static str),
53 #[error("unsupported logical encoding {0:?} for {1}")]
54 UnsupportedLogicalEncoding(LogicalEncoding, &'static str),
55 #[error("invalid combination of logical encodings: {0:?} + {1:?}")]
56 InvalidLogicalEncodings(LogicalTechnique, LogicalTechnique),
57 #[error("layer has zero size")]
58 ZeroLayerSize,
59 #[error("The profile used to optimise data is incompatible")]
60 BadProfileDataCombination,
61 #[error("The encoder used to optimise data is incompatible")]
62 BadEncoderDataCombination,
63
64 #[error("buffer underflow: needed {0} bytes, but only {1} remain")]
66 BufferUnderflow(u32, usize),
67 #[error("FastPFor decode failed: expected={0} got={1}")]
68 FastPforDecode(u32, usize),
69 #[error("invalid RLE run length (cannot convert to usize): value={0}")]
70 RleRunLenInvalid(i128),
71
72 #[error("geometry requires at least 1 stream, got 0")]
74 GeometryWithoutStreams,
75 #[error("FastPFor data byte length expected multiple of 4, got {0}")]
76 InvalidFastPforByteLength(usize),
77 #[error("vec2 delta stream size expected to be non-empty and multiple of 2, got {0}")]
78 InvalidPairStreamSize(usize),
79 #[error("decodable stream size expected {1}, got {0}")]
80 InvalidDecodingStreamSize(usize, usize),
81 #[error("stream data mismatch: expected {0}, got {1}")]
82 StreamDataMismatch(&'static str, &'static str),
83 #[error("IDs missing for encoding (expected Some IDs, got None)")]
84 IdsMissingForEncoding,
85 #[error("missing struct encoder for struct")]
86 MissingStructEncoderForStruct,
87 #[error("previous decode/parsing attempt failed")]
88 PriorParseFailure,
89 #[error("presence stream has {0} bits set but {1} values provided")]
90 PresenceValueCountMismatch(usize, usize),
91 #[error("MVT parse error: {0}")]
92 MvtParse(String),
93 #[error("need to encode before being able to write")]
94 NeedsEncodingBeforeWriting,
95 #[error("memory limit exceeded: limit={limit}, used={used}, requested={requested}")]
96 MemoryLimitExceeded {
97 limit: u32,
98 used: u32,
99 requested: u32,
100 },
101 #[error("not implemented: {0}")]
102 NotImplemented(&'static str),
103 #[error("unsupported property value and encoder combination: {0:?} + {1:?}")]
104 UnsupportedPropertyEncoderCombination(&'static str, &'static str),
105 #[error("shared dictionary requires at least 2 streams, got {0}")]
106 SharedDictRequiresStreams(usize),
107 #[error("unsupported string stream count (expected between 2 and 5): {0}")]
108 UnsupportedStringStreamCount(usize),
109 #[error("Structs are not allowed to be optional")]
110 TriedToEncodeOptionalStruct,
111 #[error(
112 "encoding instruction count mismatch: expected {input_len} instructions for {input_len} properties, got {config_len}"
113 )]
114 EncodingInstructionCountMismatch { input_len: usize, config_len: usize },
115 #[error("struct child data streams expected exactly 1 value, got {0}")]
116 UnexpectedStructChildCount(u32),
117 #[error("unsupported physical encoding: {0}")]
118 UnsupportedPhysicalEncoding(&'static str),
119 #[error("unsupported physical encoding: {0:?} for {1}")]
120 UnsupportedPhysicalEncodingForType(PhysicalEncoding, &'static str),
121 #[error(
122 "Extent {extent} cannot be encoded to morton due to morton allowing max. 16 bits, but {required_bits} would be required"
123 )]
124 VertexMortonNotCompatibleWithExtent { extent: u32, required_bits: u32 },
125
126 #[error("MVT error: {0}")]
128 BadMvtGeometry(&'static str),
129 #[error("geometry[{0}]: index out of bounds")]
130 GeometryIndexOutOfBounds(usize),
131 #[error("geometry[{index}]: {field}[{idx}] out of bounds (len={len})")]
132 GeometryOutOfBounds {
133 index: usize,
134 field: &'static str,
135 idx: usize,
136 len: usize,
137 },
138 #[error("geometry[{index}]: vertex {vertex} out of bounds (count={count})")]
139 GeometryVertexOutOfBounds {
140 index: usize,
141 vertex: usize,
142 count: usize,
143 },
144 #[error("geometry[{0}]: {1} requires geometry_offsets")]
145 NoGeometryOffsets(usize, GeometryType),
146 #[error("geometry[{0}]: {1} requires part_offsets")]
147 NoPartOffsets(usize, GeometryType),
148 #[error("geometry[{0}]: {1} requires ring_offsets")]
149 NoRingOffsets(usize, GeometryType),
150 #[error("geometry[{0}]: unexpected offset combination for {1}")]
151 UnexpectedOffsetCombination(usize, GeometryType),
152
153 #[error("FastPFor error: {0}")]
154 FastPfor(#[from] fastpfor::FastPForError),
155 #[error(transparent)]
156 Io(#[from] std::io::Error),
157 #[error("Serde JSON error: {0}")]
158 SerdeJsonError(#[from] serde_json::Error),
159 #[error("integer conversion error: {0}")]
160 TryFromIntError(#[from] TryFromIntError),
161 #[error("num_enum conversion error: {0}")]
162 TryFromPrimitive(#[from] TryFromPrimitiveError<GeometryType>),
163 #[error("UTF-8 decode error: {0}")]
164 Utf8(#[from] std::str::Utf8Error),
165 #[error("UTF-8 decode error: {0}")]
166 FromUtf8(#[from] std::string::FromUtf8Error),
167}
168
169impl From<Infallible> for MltError {
170 fn from(_: Infallible) -> Self {
171 unreachable!()
172 }
173}
174
175impl From<MltError> for std::io::Error {
176 fn from(value: MltError) -> Self {
177 match value {
178 MltError::Io(e) => e,
179 other => std::io::Error::other(other),
180 }
181 }
182}
183
184pub trait AsMltError<T> {
185 fn or_overflow(&self) -> MltResult<T>;
186}
187
188impl<T: Copy> AsMltError<T> for Option<T> {
189 #[inline]
190 fn or_overflow(&self) -> MltResult<T> {
191 self.ok_or(MltError::IntegerOverflow)
192 }
193}
194
195impl AsMltError<u32> for Result<u32, TryFromIntError> {
196 #[inline]
197 fn or_overflow(&self) -> MltResult<u32> {
198 self.map_err(|_| MltError::IntegerOverflow)
199 }
200}
201
202#[inline]
203pub fn fail_if_invalid_stream_size<T: AsUsize>(actual: T, expected: T) -> MltResult<()> {
204 if actual == expected {
205 Ok(())
206 } else {
207 Err(MltError::InvalidDecodingStreamSize(
208 actual.as_usize(),
209 expected.as_usize(),
210 ))
211 }
212}