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};
8use crate::codecs::zigzag::{decode_componentwise_delta_vec2s, decode_zigzag, decode_zigzag_delta};
9use crate::decoder::{
10 FloatLogical, IntLogical, LogicalEncoding, LogicalTechnique, LogicalValue, RleMeta, StreamMeta,
11 VertexLogical,
12};
13use crate::errors::{AsMltError as _, fail_if_invalid_stream_size};
14use crate::{Decoder, MltResult};
15
16impl RleMeta {
17 pub fn decode<T: PrimInt + Debug>(self, data: &[T], dec: &mut Decoder) -> MltResult<Vec<T>> {
35 match self {
36 Self::Split {
37 runs,
38 num_rle_values,
39 } => Self::decode_split(runs, num_rle_values, data, dec),
40 #[cfg(feature = "unstable-v2")]
41 Self::Interleaved { num_rle_values } => {
42 Self::decode_interleaved(num_rle_values, data, dec)
43 }
44 }
45 }
46
47 fn decode_split<T: PrimInt + Debug>(
49 runs: u32,
50 num_rle_values: u32,
51 data: &[T],
52 dec: &mut Decoder,
53 ) -> MltResult<Vec<T>> {
54 let expected_len = runs.into_usize().checked_mul(2).or_overflow()?;
55 fail_if_invalid_stream_size(data.len(), expected_len)?;
56
57 let (run_lens, values) = data.split_at(runs.into_usize());
58 fail_if_invalid_stream_size(
59 num_rle_values.into_usize(),
60 Self::calc_size(run_lens)?.into_usize(),
61 )?;
62
63 let alloc_size = num_rle_values.into_usize();
64 let mut result = dec.alloc(alloc_size)?;
65 for (&run_len, &val) in run_lens.iter().zip(values.iter()) {
66 let run = run_len
67 .to_usize()
68 .ok_or_else(|| RleRunLenInvalid(run_len.to_i128().unwrap_or_default()))?;
69 result.extend(repeat_n(val, run));
70 }
71 dec.adjust_alloc(&result, alloc_size)?;
72 Ok(result)
73 }
74
75 #[cfg(feature = "unstable-v2")]
78 fn decode_interleaved<T: PrimInt + Debug>(
79 num_rle_values: u32,
80 data: &[T],
81 dec: &mut Decoder,
82 ) -> MltResult<Vec<T>> {
83 if !data.len().is_multiple_of(2) {
84 return Err(RleRunLenInvalid(data.len().to_i128().unwrap_or_default()));
85 }
86 let alloc_size = num_rle_values.into_usize();
87 let mut result = dec.alloc(alloc_size)?;
88 for [cnt, val] in data.as_chunks::<2>().0 {
89 let run = cnt
90 .to_usize()
91 .filter(|&run| run <= alloc_size - result.len())
92 .ok_or_else(|| RleRunLenInvalid(cnt.to_i128().unwrap_or_default()))?;
93 result.extend(repeat_n(val, run));
94 }
95 fail_if_invalid_stream_size(result.len(), alloc_size)?;
97 dec.adjust_alloc(&result, alloc_size)?;
98 Ok(result)
99 }
100
101 fn calc_size<T: PrimInt + Debug>(run_lens: &[T]) -> MltResult<u32> {
102 run_lens
103 .iter()
104 .try_fold(T::zero(), |a, v| a.checked_add(v))
105 .and_then(|v| v.to_u32())
106 .ok_or_else(|| RleRunLenInvalid(run_lens.len().to_i128().unwrap_or_default()))
107 }
108}
109
110impl LogicalTechnique {
111 pub fn parse(value: u8) -> MltResult<Self> {
112 Self::try_from(value).or(Err(ParsingLogicalTechnique(value)))
113 }
114}
115
116impl LogicalValue {
117 #[must_use]
118 pub fn new(meta: StreamMeta) -> Self {
119 Self { meta }
120 }
121
122 pub fn decode_i32(self, data: &[u32], dec: &mut Decoder) -> MltResult<Vec<i32>> {
127 use IntLogical as IL;
128 use LogicalEncoding as LE;
129 use VertexLogical as VL;
130
131 match self.meta.encoding.logical {
132 LE::Int(IL::None) | LE::Vertex(VL::None) => decode_zigzag(data, dec),
133 LE::Int(IL::Rle(v)) => decode_zigzag(&v.decode(data, dec)?, dec),
134 LE::Vertex(VL::ComponentwiseDelta) => decode_componentwise_delta_vec2s(data, dec),
135 LE::Int(IL::Delta) | LE::Vertex(VL::Delta) => decode_zigzag_delta::<i32, _>(data, dec),
136 LE::Int(IL::DeltaRle(v)) => {
137 let expanded = v.decode(data, dec)?;
138 decode_zigzag_delta::<i32, _>(&expanded, dec)
139 }
140 LE::Vertex(VL::Morton(v)) => v.decode_codes(data, dec),
141 LE::Vertex(VL::MortonDelta(v)) => v.decode_delta(data, dec),
142 LE::Vertex(VL::MortonRle(_)) => Err(UnsupportedLogicalEncoding(
143 self.meta.encoding.logical,
144 "i32 (MortonRle)",
145 )),
146 LE::Bool(_) | LE::Float(_) => Err(UnsupportedLogicalEncoding(
147 self.meta.encoding.logical,
148 "i32",
149 )),
150 }
151 }
152
153 pub fn decode_u32(self, data: &[u32], dec: &mut Decoder) -> MltResult<Vec<u32>> {
158 let num = self.meta.num_values.into_usize();
159 match self.meta.encoding.logical {
160 LogicalEncoding::Int(IntLogical::None) | LogicalEncoding::Float(FloatLogical::Dict) => {
161 dec.consume_items::<u32>(num)?;
163 Ok(data.to_vec())
164 }
165 LogicalEncoding::Int(IntLogical::Rle(rle)) => rle.decode(data, dec),
166 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i32, _>(data, dec),
167 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
168 decode_zigzag_delta::<i32, _>(&rle.decode(data, dec)?, dec)
169 }
170 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
171 Err(UnsupportedLogicalEncoding(
172 self.meta.encoding.logical,
173 "u32",
174 ))
175 }
176 }
177 }
178
179 pub fn decode_i64(self, data: &[u64], dec: &mut Decoder) -> MltResult<Vec<i64>> {
184 match self.meta.encoding.logical {
185 LogicalEncoding::Int(IntLogical::None) => decode_zigzag(data, dec),
186 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i64, _>(data, dec),
187 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
188 let expanded = rle.decode(data, dec)?;
189 decode_zigzag_delta::<i64, _>(&expanded, dec)
190 }
191 LogicalEncoding::Int(IntLogical::Rle(rle)) => {
192 let expanded = rle.decode(data, dec)?;
194 decode_zigzag(&expanded, dec)
195 }
196 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
197 Err(UnsupportedLogicalEncoding(
198 self.meta.encoding.logical,
199 "i64",
200 ))
201 }
202 }
203 }
204
205 pub fn decode_u64(self, data: &[u64], dec: &mut Decoder) -> MltResult<Vec<u64>> {
210 let num = self.meta.num_values.into_usize();
211 match self.meta.encoding.logical {
212 LogicalEncoding::Int(IntLogical::None) | LogicalEncoding::Float(FloatLogical::Dict) => {
213 dec.consume_items::<u64>(num)?;
215 Ok(data.to_vec())
216 }
217 LogicalEncoding::Int(IntLogical::Rle(rle)) => rle.decode(data, dec),
218 LogicalEncoding::Int(IntLogical::Delta) => decode_zigzag_delta::<i64, _>(data, dec),
219 LogicalEncoding::Int(IntLogical::DeltaRle(rle)) => {
220 let expanded = rle.decode(data, dec)?;
221 decode_zigzag_delta::<i64, _>(&expanded, dec)
222 }
223 LogicalEncoding::Bool(_) | LogicalEncoding::Float(_) | LogicalEncoding::Vertex(_) => {
224 Err(UnsupportedLogicalEncoding(
225 self.meta.encoding.logical,
226 "u64",
227 ))
228 }
229 }
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236 use crate::MltError::InvalidDecodingStreamSize;
237 use crate::test_helpers::dec;
238
239 #[test]
240 fn test_decode_rle_empty() {
241 let rle = RleMeta::Split {
242 runs: 0,
243 num_rle_values: 0,
244 };
245 assert_eq!(rle.decode::<u32>(&[], &mut dec()).unwrap(), [] as [u32; 0]);
246 }
247
248 #[test]
249 fn test_decode_rle_invalid_stream_size() {
250 let rle = RleMeta::Split {
252 runs: 2,
253 num_rle_values: 3,
254 };
255 let data = [1u32, 2, 3];
256 let err = rle.decode::<u32>(&data, &mut dec()).unwrap_err();
257 assert!(matches!(err, InvalidDecodingStreamSize(3, 4)));
258 }
259
260 #[cfg(feature = "unstable-v2")]
261 #[test]
262 fn test_decode_rle_interleaved() {
263 let rle = RleMeta::Interleaved { num_rle_values: 6 };
264 let data = [3u32, 7, 1, 9, 2, 7];
266 let decoded = rle.decode(&data, &mut dec()).unwrap();
267 assert_eq!(decoded, vec![7, 7, 7, 9, 7, 7]);
268 }
269
270 #[cfg(feature = "unstable-v2")]
271 #[test]
272 fn test_decode_rle_interleaved_empty() {
273 let rle = RleMeta::Interleaved { num_rle_values: 0 };
274 assert!(rle.decode::<u32>(&[], &mut dec()).unwrap().is_empty());
275 }
276
277 #[cfg(feature = "unstable-v2")]
278 #[test]
279 fn test_decode_rle_interleaved_count_mismatch() {
280 let rle = RleMeta::Interleaved { num_rle_values: 5 };
282 let data = [3u32, 7, 1, 9];
283 assert!(rle.decode(&data, &mut dec()).is_err());
284 }
285
286 #[cfg(feature = "unstable-v2")]
287 #[test]
288 fn test_decode_rle_interleaved_odd_length() {
289 let rle = RleMeta::Interleaved { num_rle_values: 3 };
290 let data = [3u32, 7, 1];
291 assert!(rle.decode(&data, &mut dec()).is_err());
292 }
293
294 #[cfg(feature = "unstable-v2")]
295 #[test]
296 fn test_decode_rle_interleaved_overflowing_run() {
297 let rle = RleMeta::Interleaved { num_rle_values: 2 };
299 let data = [u32::MAX, 7];
300 assert!(rle.decode(&data, &mut dec()).is_err());
301 }
302}