1use std::fmt::Debug;
2use std::iter::repeat_n;
3
4use num_traits::{PrimInt, ToPrimitive as _};
5use usize_cast::IntoUsize as _;
6
7use crate::MltError::{ParsingLogicalTechnique, RleRunLenInvalid, UnsupportedLogicalEncoding};
8#[cfg(feature = "unstable-v2")]
9use crate::codecs::zigzag::decode_componentwise_delta_vec3s;
10use crate::codecs::zigzag::{
11 decode_componentwise_delta_vec2s, decode_componentwise_delta2_vec2s, decode_zigzag,
12 decode_zigzag_delta, decode_zigzag_delta2,
13};
14#[cfg(feature = "unstable-v2")]
15use crate::decoder::XyzLogical;
16use crate::decoder::{
17 FloatLogical, IntLogical, LogicalEncoding, LogicalTechnique, LogicalValue, RleMeta, StreamMeta,
18 VertexLogical,
19};
20use crate::errors::{AsMltError as _, fail_if_invalid_stream_size};
21use crate::{Decoder, MltResult};
22
23impl RleMeta {
24 pub fn decode<T: PrimInt + Debug>(self, data: &[T], dec: &mut Decoder) -> MltResult<Vec<T>> {
42 match self {
43 Self::Split {
44 runs,
45 num_rle_values,
46 } => Self::decode_split(runs, num_rle_values, data, dec),
47 #[cfg(feature = "unstable-v2")]
48 Self::Interleaved { num_rle_values } => {
49 Self::decode_interleaved(num_rle_values, data, dec)
50 }
51 }
52 }
53
54 fn decode_split<T: PrimInt + Debug>(
56 runs: u32,
57 num_rle_values: u32,
58 data: &[T],
59 dec: &mut Decoder,
60 ) -> MltResult<Vec<T>> {
61 let expected_len = runs.into_usize().checked_mul(2).or_overflow()?;
62 fail_if_invalid_stream_size(data.len(), expected_len)?;
63
64 let (run_lens, values) = data.split_at(runs.into_usize());
65 fail_if_invalid_stream_size(
66 num_rle_values.into_usize(),
67 Self::calc_size(run_lens)?.into_usize(),
68 )?;
69
70 let alloc_size = num_rle_values.into_usize();
71 let mut result = dec.alloc(alloc_size)?;
72 for (&run_len, &val) in run_lens.iter().zip(values.iter()) {
73 let run = run_len
74 .to_usize()
75 .ok_or_else(|| RleRunLenInvalid(run_len.to_i128().unwrap_or_default()))?;
76 result.extend(repeat_n(val, run));
77 }
78 dec.adjust_alloc(&result, alloc_size)?;
79 Ok(result)
80 }
81
82 #[cfg(feature = "unstable-v2")]
85 fn decode_interleaved<T: PrimInt + Debug>(
86 num_rle_values: u32,
87 data: &[T],
88 dec: &mut Decoder,
89 ) -> MltResult<Vec<T>> {
90 if !data.len().is_multiple_of(2) {
91 return Err(RleRunLenInvalid(data.len().to_i128().unwrap_or_default()));
92 }
93 let alloc_size = num_rle_values.into_usize();
94 let mut result = dec.alloc(alloc_size)?;
95 for [cnt, val] in data.as_chunks::<2>().0 {
96 let run = cnt
97 .to_usize()
98 .filter(|&run| run <= alloc_size - result.len())
99 .ok_or_else(|| RleRunLenInvalid(cnt.to_i128().unwrap_or_default()))?;
100 result.extend(repeat_n(val, run));
101 }
102 fail_if_invalid_stream_size(result.len(), alloc_size)?;
104 dec.adjust_alloc(&result, alloc_size)?;
105 Ok(result)
106 }
107
108 fn calc_size<T: PrimInt + Debug>(run_lens: &[T]) -> MltResult<u32> {
109 run_lens
110 .iter()
111 .try_fold(T::zero(), |a, v| a.checked_add(v))
112 .and_then(|v| v.to_u32())
113 .ok_or_else(|| RleRunLenInvalid(run_lens.len().to_i128().unwrap_or_default()))
114 }
115}
116
117impl LogicalTechnique {
118 pub fn parse(value: u8) -> MltResult<Self> {
119 Self::try_from(value).or(Err(ParsingLogicalTechnique(value)))
120 }
121}
122
123impl LogicalValue {
124 #[must_use]
125 pub fn new(meta: StreamMeta) -> Self {
126 Self { meta }
127 }
128
129 pub fn decode_i32(self, data: &[u32], dec: &mut Decoder) -> MltResult<Vec<i32>> {
134 use IntLogical as IL;
135 use LogicalEncoding as LE;
136 use VertexLogical as VL;
137
138 match self.meta.encoding.logical {
139 LE::Int(IL::None) | LE::Vertex(VL::None) => decode_zigzag(data, dec),
140 LE::Int(IL::Rle(v)) => decode_zigzag(&v.decode(data, dec)?, dec),
141 LE::Vertex(VL::ComponentwiseDelta) => decode_componentwise_delta_vec2s(data, dec),
142 LE::Int(IL::Delta) | LE::Vertex(VL::Delta) => decode_zigzag_delta::<i32, _>(data, dec),
143 LE::Int(IL::DeltaRle(v)) => {
144 let expanded = v.decode(data, dec)?;
145 decode_zigzag_delta::<i32, _>(&expanded, dec)
146 }
147 LE::Int(IL::Delta2) => decode_zigzag_delta2::<i32, _>(data, dec),
148 LE::Vertex(VL::ComponentwiseDelta2) => decode_componentwise_delta2_vec2s(data, dec),
149 LE::Vertex(VL::MortonDelta(v)) => v.decode_delta(data, dec),
150 #[cfg(feature = "unstable-v2")]
151 LE::Vertex(VL::Xyz(_, xyz)) => {
152 if !data.len().is_multiple_of(3) {
153 return Err(crate::MltError::InvalidTripleStreamSize(data.len()));
154 }
155 match xyz {
156 XyzLogical::None => decode_zigzag(data, dec),
157 XyzLogical::Delta => decode_zigzag_delta::<i32, _>(data, dec),
158 XyzLogical::ComponentwiseDelta => decode_componentwise_delta_vec3s(data, dec),
159 }
160 }
161 LE::Bool(_) | LE::Float(_) => Err(UnsupportedLogicalEncoding(
162 self.meta.encoding.logical,
163 "i32",
164 )),
165 }
166 }
167
168 pub fn decode_u32(self, data: &[u32], dec: &mut Decoder) -> MltResult<Vec<u32>> {
173 let num = self.meta.num_values.into_usize();
174 match self.meta.encoding.logical {
175 LogicalEncoding::Int(IntLogical::None) | LogicalEncoding::Float(FloatLogical::Dict) => {
176 dec.consume_items::<u32>(num)?;
178 Ok(data.to_vec())
179 }
180 LogicalEncoding::Int(IntLogical::Rle(rle)) => rle.decode(data, dec),
181 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i32, _>(data, dec),
182 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
183 decode_zigzag_delta::<i32, _>(&rle.decode(data, dec)?, dec)
184 }
185 LogicalEncoding::Int(IntLogical::Delta2) => decode_zigzag_delta2::<i32, _>(data, dec),
186 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
187 Err(UnsupportedLogicalEncoding(
188 self.meta.encoding.logical,
189 "u32",
190 ))
191 }
192 }
193 }
194
195 pub fn decode_i64(self, data: &[u64], dec: &mut Decoder) -> MltResult<Vec<i64>> {
200 match self.meta.encoding.logical {
201 LogicalEncoding::Int(IntLogical::None) => decode_zigzag(data, dec),
202 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i64, _>(data, dec),
203 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
204 let expanded = rle.decode(data, dec)?;
205 decode_zigzag_delta::<i64, _>(&expanded, dec)
206 }
207 LogicalEncoding::Int(IntLogical::Rle(rle)) => {
208 let expanded = rle.decode(data, dec)?;
210 decode_zigzag(&expanded, dec)
211 }
212 LogicalEncoding::Int(IntLogical::Delta2) => decode_zigzag_delta2::<i64, _>(data, dec),
213 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
214 Err(UnsupportedLogicalEncoding(
215 self.meta.encoding.logical,
216 "i64",
217 ))
218 }
219 }
220 }
221
222 pub fn decode_u64(self, data: &[u64], dec: &mut Decoder) -> MltResult<Vec<u64>> {
227 let num = self.meta.num_values.into_usize();
228 match self.meta.encoding.logical {
229 LogicalEncoding::Int(IntLogical::None) | LogicalEncoding::Float(FloatLogical::Dict) => {
230 dec.consume_items::<u64>(num)?;
232 Ok(data.to_vec())
233 }
234 LogicalEncoding::Int(IntLogical::Rle(rle)) => rle.decode(data, dec),
235 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i64, _>(data, dec),
236 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
237 let expanded = rle.decode(data, dec)?;
238 decode_zigzag_delta::<i64, _>(&expanded, dec)
239 }
240 LogicalEncoding::Int(IntLogical::Delta2) => decode_zigzag_delta2::<i64, _>(data, dec),
241 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
242 Err(UnsupportedLogicalEncoding(
243 self.meta.encoding.logical,
244 "u64",
245 ))
246 }
247 }
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 use super::*;
254 use crate::MltError::InvalidDecodingStreamSize;
255 use crate::test_helpers::dec;
256
257 #[test]
258 fn test_decode_rle_empty() {
259 let rle = RleMeta::Split {
260 runs: 0,
261 num_rle_values: 0,
262 };
263 assert_eq!(rle.decode::<u32>(&[], &mut dec()).unwrap(), [] as [u32; 0]);
264 }
265
266 #[test]
267 fn test_decode_rle_invalid_stream_size() {
268 let rle = RleMeta::Split {
270 runs: 2,
271 num_rle_values: 3,
272 };
273 let data = [1u32, 2, 3];
274 let err = rle.decode::<u32>(&data, &mut dec()).unwrap_err();
275 assert!(matches!(err, InvalidDecodingStreamSize(3, 4)));
276 }
277
278 fn value(logical: LogicalEncoding) -> LogicalValue {
279 use crate::decoder::{DictionaryType, IntEncoding, PhysicalEncoding, StreamType};
280
281 let encoding = IntEncoding::new(logical, PhysicalEncoding::VarInt);
282 LogicalValue::new(StreamMeta::new(
283 StreamType::Data(DictionaryType::None),
284 encoding,
285 2,
286 ))
287 }
288
289 #[test]
290 fn a_raw_u64_stream_passes_through() {
291 let decoded = value(LogicalEncoding::Int(IntLogical::None))
292 .decode_u64(&[7, 9], &mut dec())
293 .unwrap();
294 assert_eq!(decoded, [7, 9]);
295 }
296
297 #[rstest::rstest]
298 #[case::i32_bool(LogicalEncoding::Bool(crate::decoder::BoolLogical::None), "i32")]
299 #[case::i32_float(LogicalEncoding::Float(FloatLogical::None), "i32")]
300 #[case::u32_vertex(LogicalEncoding::Vertex(VertexLogical::None), "u32")]
301 #[case::i64_bool(LogicalEncoding::Bool(crate::decoder::BoolLogical::None), "i64")]
302 #[case::u64_float(LogicalEncoding::Float(FloatLogical::None), "u64")]
303 fn a_decoder_rejects_an_encoding_of_another_kind(
304 #[case] logical: LogicalEncoding,
305 #[case] target: &str,
306 ) {
307 let v = value(logical);
308 let err = match target {
309 "u32" => v.decode_u32(&[], &mut dec()).map(drop),
310 "i64" => v.decode_i64(&[], &mut dec()).map(drop),
311 "u64" => v.decode_u64(&[], &mut dec()).map(drop),
312 _ => v.decode_i32(&[], &mut dec()).map(drop),
313 }
314 .unwrap_err();
315 assert!(matches!(err, UnsupportedLogicalEncoding(l, t) if l == logical && t == target));
316 }
317
318 #[cfg(feature = "unstable-v2")]
319 #[test]
320 fn test_decode_rle_interleaved() {
321 let rle = RleMeta::Interleaved { num_rle_values: 6 };
322 let data = [3u32, 7, 1, 9, 2, 7];
324 let decoded = rle.decode(&data, &mut dec()).unwrap();
325 assert_eq!(decoded, vec![7, 7, 7, 9, 7, 7]);
326 }
327
328 #[cfg(feature = "unstable-v2")]
329 #[test]
330 fn test_decode_rle_interleaved_empty() {
331 let rle = RleMeta::Interleaved { num_rle_values: 0 };
332 assert_eq!(
333 rle.decode::<u32>(&[], &mut dec()).unwrap(),
334 Vec::<u32>::new()
335 );
336 }
337
338 #[cfg(feature = "unstable-v2")]
339 #[test]
340 fn test_decode_rle_interleaved_count_mismatch() {
341 let rle = RleMeta::Interleaved { num_rle_values: 5 };
343 let data = [3u32, 7, 1, 9];
344 assert!(rle.decode(&data, &mut dec()).is_err());
345 }
346
347 #[cfg(feature = "unstable-v2")]
348 #[test]
349 fn test_decode_rle_interleaved_odd_length() {
350 let rle = RleMeta::Interleaved { num_rle_values: 3 };
351 let data = [3u32, 7, 1];
352 assert!(rle.decode(&data, &mut dec()).is_err());
353 }
354
355 #[cfg(feature = "unstable-v2")]
356 #[test]
357 fn test_decode_rle_interleaved_overflowing_run() {
358 let rle = RleMeta::Interleaved { num_rle_values: 2 };
360 let data = [u32::MAX, 7];
361 assert!(rle.decode(&data, &mut dec()).is_err());
362 }
363
364 #[cfg(feature = "unstable-v2")]
365 fn xyz(logical: XyzLogical) -> LogicalValue {
366 use crate::decoder::{DictionaryType, IntEncoding, PhysicalEncoding, StreamType};
367 use crate::tile::ZStep;
368
369 let encoding = IntEncoding::new(
370 LogicalEncoding::Vertex(VertexLogical::Xyz(ZStep::new(0).unwrap(), logical)),
371 PhysicalEncoding::VarInt,
372 );
373 LogicalValue::new(StreamMeta::new(
374 StreamType::Data(DictionaryType::Vertex),
375 encoding,
376 2,
377 ))
378 }
379
380 #[cfg(feature = "unstable-v2")]
381 #[rstest::rstest]
382 #[case::none(XyzLogical::None, [1, 2, -1, 3, 4, -2])]
383 #[case::delta(XyzLogical::Delta, [1, 3, 2, 5, 9, 7])]
384 #[case::componentwise_delta(XyzLogical::ComponentwiseDelta, [1, 2, -1, 4, 6, -3])]
385 fn an_xyz_stream_decodes_its_triples(#[case] logical: XyzLogical, #[case] expected: [i32; 6]) {
386 let zigzag = [2, 4, 1, 6, 8, 3];
387 assert_eq!(
388 xyz(logical).decode_i32(&zigzag, &mut dec()).unwrap(),
389 expected
390 );
391 }
392
393 #[cfg(feature = "unstable-v2")]
394 #[test]
395 fn an_xyz_stream_of_partial_triples_is_rejected() {
396 let err = xyz(XyzLogical::None)
397 .decode_i32(&[2, 4, 1, 6], &mut dec())
398 .unwrap_err();
399 assert!(matches!(err, crate::MltError::InvalidTripleStreamSize(4)));
400 }
401}