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 LE::Vertex(VL::Rans) => Err(UnsupportedLogicalEncoding(
151 self.meta.encoding.logical,
152 "a stream decoded without the layer's topology",
153 )),
154 #[cfg(feature = "unstable-v2")]
155 LE::Vertex(VL::Xyz(_, xyz)) => {
156 if !data.len().is_multiple_of(3) {
157 return Err(crate::MltError::InvalidTripleStreamSize(data.len()));
158 }
159 match xyz {
160 XyzLogical::None => decode_zigzag(data, dec),
161 XyzLogical::Delta => decode_zigzag_delta::<i32, _>(data, dec),
162 XyzLogical::ComponentwiseDelta => decode_componentwise_delta_vec3s(data, dec),
163 }
164 }
165 LE::Bool(_) | LE::Float(_) => Err(UnsupportedLogicalEncoding(
166 self.meta.encoding.logical,
167 "i32",
168 )),
169 }
170 }
171
172 pub fn decode_u32(self, data: &[u32], dec: &mut Decoder) -> MltResult<Vec<u32>> {
177 let num = self.meta.num_values.into_usize();
178 match self.meta.encoding.logical {
179 LogicalEncoding::Int(IntLogical::None) | LogicalEncoding::Float(FloatLogical::Dict) => {
180 dec.consume_items::<u32>(num)?;
182 Ok(data.to_vec())
183 }
184 LogicalEncoding::Int(IntLogical::Rle(rle)) => rle.decode(data, dec),
185 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i32, _>(data, dec),
186 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
187 decode_zigzag_delta::<i32, _>(&rle.decode(data, dec)?, dec)
188 }
189 LogicalEncoding::Int(IntLogical::Delta2) => decode_zigzag_delta2::<i32, _>(data, dec),
190 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
191 Err(UnsupportedLogicalEncoding(
192 self.meta.encoding.logical,
193 "u32",
194 ))
195 }
196 }
197 }
198
199 pub fn decode_i64(self, data: &[u64], dec: &mut Decoder) -> MltResult<Vec<i64>> {
204 match self.meta.encoding.logical {
205 LogicalEncoding::Int(IntLogical::None) => decode_zigzag(data, dec),
206 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i64, _>(data, dec),
207 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
208 let expanded = rle.decode(data, dec)?;
209 decode_zigzag_delta::<i64, _>(&expanded, dec)
210 }
211 LogicalEncoding::Int(IntLogical::Rle(rle)) => {
212 let expanded = rle.decode(data, dec)?;
214 decode_zigzag(&expanded, dec)
215 }
216 LogicalEncoding::Int(IntLogical::Delta2) => decode_zigzag_delta2::<i64, _>(data, dec),
217 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
218 Err(UnsupportedLogicalEncoding(
219 self.meta.encoding.logical,
220 "i64",
221 ))
222 }
223 }
224 }
225
226 pub fn decode_u64(self, data: &[u64], dec: &mut Decoder) -> MltResult<Vec<u64>> {
231 let num = self.meta.num_values.into_usize();
232 match self.meta.encoding.logical {
233 LogicalEncoding::Int(IntLogical::None) | LogicalEncoding::Float(FloatLogical::Dict) => {
234 dec.consume_items::<u64>(num)?;
236 Ok(data.to_vec())
237 }
238 LogicalEncoding::Int(IntLogical::Rle(rle)) => rle.decode(data, dec),
239 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i64, _>(data, dec),
240 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
241 let expanded = rle.decode(data, dec)?;
242 decode_zigzag_delta::<i64, _>(&expanded, dec)
243 }
244 LogicalEncoding::Int(IntLogical::Delta2) => decode_zigzag_delta2::<i64, _>(data, dec),
245 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
246 Err(UnsupportedLogicalEncoding(
247 self.meta.encoding.logical,
248 "u64",
249 ))
250 }
251 }
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258 use crate::MltError::InvalidDecodingStreamSize;
259 use crate::test_helpers::dec;
260
261 #[test]
262 fn test_decode_rle_empty() {
263 let rle = RleMeta::Split {
264 runs: 0,
265 num_rle_values: 0,
266 };
267 assert_eq!(rle.decode::<u32>(&[], &mut dec()).unwrap(), [] as [u32; 0]);
268 }
269
270 #[test]
271 fn test_decode_rle_invalid_stream_size() {
272 let rle = RleMeta::Split {
274 runs: 2,
275 num_rle_values: 3,
276 };
277 let data = [1u32, 2, 3];
278 let err = rle.decode::<u32>(&data, &mut dec()).unwrap_err();
279 assert!(matches!(err, InvalidDecodingStreamSize(3, 4)));
280 }
281
282 fn value(logical: LogicalEncoding) -> LogicalValue {
283 use crate::decoder::{DictionaryType, IntEncoding, PhysicalEncoding, StreamType};
284
285 let encoding = IntEncoding::new(logical, PhysicalEncoding::VarInt);
286 LogicalValue::new(StreamMeta::new(
287 StreamType::Data(DictionaryType::None),
288 encoding,
289 2,
290 ))
291 }
292
293 #[test]
294 fn a_raw_u64_stream_passes_through() {
295 let decoded = value(LogicalEncoding::Int(IntLogical::None))
296 .decode_u64(&[7, 9], &mut dec())
297 .unwrap();
298 assert_eq!(decoded, [7, 9]);
299 }
300
301 #[rstest::rstest]
302 #[case::i32_bool(LogicalEncoding::Bool(crate::decoder::BoolLogical::None), "i32")]
303 #[case::i32_float(LogicalEncoding::Float(FloatLogical::None), "i32")]
304 #[case::u32_vertex(LogicalEncoding::Vertex(VertexLogical::None), "u32")]
305 #[case::i64_bool(LogicalEncoding::Bool(crate::decoder::BoolLogical::None), "i64")]
306 #[case::u64_float(LogicalEncoding::Float(FloatLogical::None), "u64")]
307 fn a_decoder_rejects_an_encoding_of_another_kind(
308 #[case] logical: LogicalEncoding,
309 #[case] target: &str,
310 ) {
311 let v = value(logical);
312 let err = match target {
313 "u32" => v.decode_u32(&[], &mut dec()).map(drop),
314 "i64" => v.decode_i64(&[], &mut dec()).map(drop),
315 "u64" => v.decode_u64(&[], &mut dec()).map(drop),
316 _ => v.decode_i32(&[], &mut dec()).map(drop),
317 }
318 .unwrap_err();
319 assert!(matches!(err, UnsupportedLogicalEncoding(l, t) if l == logical && t == target));
320 }
321
322 #[cfg(feature = "unstable-v2")]
323 #[test]
324 fn test_decode_rle_interleaved() {
325 let rle = RleMeta::Interleaved { num_rle_values: 6 };
326 let data = [3u32, 7, 1, 9, 2, 7];
328 let decoded = rle.decode(&data, &mut dec()).unwrap();
329 assert_eq!(decoded, vec![7, 7, 7, 9, 7, 7]);
330 }
331
332 #[cfg(feature = "unstable-v2")]
333 #[test]
334 fn test_decode_rle_interleaved_empty() {
335 let rle = RleMeta::Interleaved { num_rle_values: 0 };
336 assert_eq!(
337 rle.decode::<u32>(&[], &mut dec()).unwrap(),
338 Vec::<u32>::new()
339 );
340 }
341
342 #[cfg(feature = "unstable-v2")]
343 #[test]
344 fn test_decode_rle_interleaved_count_mismatch() {
345 let rle = RleMeta::Interleaved { num_rle_values: 5 };
347 let data = [3u32, 7, 1, 9];
348 assert!(rle.decode(&data, &mut dec()).is_err());
349 }
350
351 #[cfg(feature = "unstable-v2")]
352 #[test]
353 fn test_decode_rle_interleaved_odd_length() {
354 let rle = RleMeta::Interleaved { num_rle_values: 3 };
355 let data = [3u32, 7, 1];
356 assert!(rle.decode(&data, &mut dec()).is_err());
357 }
358
359 #[cfg(feature = "unstable-v2")]
360 #[test]
361 fn test_decode_rle_interleaved_overflowing_run() {
362 let rle = RleMeta::Interleaved { num_rle_values: 2 };
364 let data = [u32::MAX, 7];
365 assert!(rle.decode(&data, &mut dec()).is_err());
366 }
367
368 #[cfg(feature = "unstable-v2")]
369 fn xyz(logical: XyzLogical) -> LogicalValue {
370 use crate::decoder::{DictionaryType, IntEncoding, PhysicalEncoding, StreamType};
371 use crate::tile::ZStep;
372
373 let encoding = IntEncoding::new(
374 LogicalEncoding::Vertex(VertexLogical::Xyz(ZStep::new(0).unwrap(), logical)),
375 PhysicalEncoding::VarInt,
376 );
377 LogicalValue::new(StreamMeta::new(
378 StreamType::Data(DictionaryType::Vertex),
379 encoding,
380 2,
381 ))
382 }
383
384 #[cfg(feature = "unstable-v2")]
385 #[rstest::rstest]
386 #[case::none(XyzLogical::None, [1, 2, -1, 3, 4, -2])]
387 #[case::delta(XyzLogical::Delta, [1, 3, 2, 5, 9, 7])]
388 #[case::componentwise_delta(XyzLogical::ComponentwiseDelta, [1, 2, -1, 4, 6, -3])]
389 fn an_xyz_stream_decodes_its_triples(#[case] logical: XyzLogical, #[case] expected: [i32; 6]) {
390 let zigzag = [2, 4, 1, 6, 8, 3];
391 assert_eq!(
392 xyz(logical).decode_i32(&zigzag, &mut dec()).unwrap(),
393 expected
394 );
395 }
396
397 #[cfg(feature = "unstable-v2")]
398 #[test]
399 fn an_xyz_stream_of_partial_triples_is_rejected() {
400 let err = xyz(XyzLogical::None)
401 .decode_i32(&[2, 4, 1, 6], &mut dec())
402 .unwrap_err();
403 assert!(matches!(err, crate::MltError::InvalidTripleStreamSize(4)));
404 }
405}