1use bytes::Bytes;
31
32use super::decoder::{PreparedFixedLenByteArrayPage, normalize_fixed_len_byte_array_data};
33use crate::basic::Encoding;
34use crate::data_type::Int32Type;
35use crate::encodings::decoding::{Decoder, DeltaBitPackDecoder};
36use crate::errors::{ParquetError, Result};
37
38pub(super) fn prepare_v1_page(
44 page: &mut PreparedFixedLenByteArrayPage,
45 num_levels: usize,
46 type_length: usize,
47 count_values: &impl Fn() -> Result<usize>,
48) -> Result<bool> {
49 let (num_values, deferred) = match page.encoding {
50 Encoding::PLAIN
51 if num_levels != 0
52 && type_length != 0
53 && may_be_length_prefixed_plain(&page.data, type_length) =>
54 {
55 (count_values()?, false)
58 }
59 Encoding::DELTA_LENGTH_BYTE_ARRAY => {
60 if num_levels == 0 || type_length == 0 {
61 (count_values()?, false)
62 } else {
63 let declared = delta_length_value_count(page.data.clone())?;
64 if declared > num_levels {
65 return Err(general_err!(
66 "DELTA_LENGTH_BYTE_ARRAY has more values than levels"
67 ));
68 }
69 (declared, true)
70 }
71 }
72 _ => return Ok(false),
73 };
74 let (encoding, data) = normalize_fixed_len_byte_array_data(
75 std::mem::take(&mut page.data),
76 num_values,
77 type_length,
78 page.encoding,
79 )?;
80 page.encoding = encoding;
81 page.validate_count = deferred;
82 page.data = data;
83 Ok(true)
84}
85
86fn may_be_length_prefixed_plain(data: &[u8], type_length: usize) -> bool {
90 let Some(stride) = type_length.checked_add(4) else {
91 return false;
92 };
93 !data.is_empty()
94 && data.len().is_multiple_of(stride)
95 && data
96 .chunks_exact(stride)
97 .take(5)
98 .all(|value| u32::from_le_bytes(value[..4].try_into().unwrap()) as usize == type_length)
99}
100
101fn delta_length_value_count(data: Bytes) -> Result<usize> {
104 let mut decoder = DeltaBitPackDecoder::<Int32Type>::new();
105 decoder.set_data(data, 0)?;
106 Ok(decoder.values_left())
107}
108
109#[cold]
113pub(super) fn decode_length_prefixed_plain(
114 data: Bytes,
115 num_values: usize,
116 type_length: usize,
117 expected_len: usize,
118 page: &str,
119) -> Result<Bytes> {
120 let stride = type_length.checked_add(4);
121 if stride.and_then(|s| num_values.checked_mul(s)) != Some(data.len()) {
122 return Err(general_err!(
123 "Invalid FIXED_LEN_BYTE_ARRAY {} payload length: expected {} bytes \
124 ({} values of {} bytes), got {}",
125 page,
126 expected_len,
127 num_values,
128 type_length,
129 data.len()
130 ));
131 }
132 let stride = stride.unwrap();
134 for value in data.chunks_exact(stride) {
135 let length = u32::from_le_bytes(value[..4].try_into().unwrap()) as usize;
136 if length != type_length {
137 return Err(general_err!(
138 "Invalid FIXED_LEN_BYTE_ARRAY {} payload length prefix: expected {}, got {}",
139 page,
140 type_length,
141 length
142 ));
143 }
144 }
145
146 let mut values = Vec::with_capacity(expected_len);
148 for value in data.chunks_exact(stride) {
149 values.extend_from_slice(&value[4..]);
150 }
151 Ok(values.into())
152}
153
154#[cold]
158pub(super) fn decode_delta_length(
159 data: Bytes,
160 num_values: usize,
161 type_length: usize,
162 expected_len: usize,
163) -> Result<Bytes> {
164 let mut decoder = DeltaBitPackDecoder::<Int32Type>::new();
165 decoder.set_data(data.clone(), num_values)?;
166 if decoder.values_left() != num_values {
167 return Err(general_err!(
168 "Invalid FIXED_LEN_BYTE_ARRAY DELTA_LENGTH_BYTE_ARRAY value count: expected {}, got {}",
169 num_values,
170 decoder.values_left()
171 ));
172 }
173 let mut lengths = [0_i32; 128];
175 let mut remaining = num_values;
176 while remaining != 0 {
177 let count = remaining.min(lengths.len());
178 let read = decoder.get(&mut lengths[..count])?;
179 if read != count {
180 return Err(general_err!(
181 "Truncated FLBA DELTA_LENGTH_BYTE_ARRAY lengths"
182 ));
183 }
184 for &length in &lengths[..count] {
185 if usize::try_from(length).ok() != Some(type_length) {
186 return Err(general_err!(
187 "Invalid FIXED_LEN_BYTE_ARRAY DELTA_LENGTH_BYTE_ARRAY value length: expected {}, got {}",
188 type_length,
189 length
190 ));
191 }
192 }
193 remaining -= count;
194 }
195 let offset = decoder.get_offset();
196 if data.len().checked_sub(offset) != Some(expected_len) {
197 return Err(general_err!(
198 "Invalid FIXED_LEN_BYTE_ARRAY DELTA_LENGTH_BYTE_ARRAY payload length: expected {} value bytes",
199 expected_len
200 ));
201 }
202 Ok(data.slice(offset..))
203}
204
205#[cfg(test)]
206mod tests {
207 use super::*;
208 use crate::basic::Encoding;
209 use crate::column::reader::decoder::{
210 normalize_fixed_len_byte_array_data, normalize_fixed_len_byte_array_payload,
211 };
212 use crate::column::reader::tests::{
213 check_incremental_fixed_len_byte_array_pages, nullable_fixed_page, nullable_fixed_reader,
214 };
215 use crate::encodings::encoding::{DeltaBitPackEncoder, Encoder};
216 use rand::{prelude::*, rngs::StdRng};
217
218 #[test]
219 fn ordinary_pages_do_not_request_compatibility_counting() {
220 for encoding in [
221 Encoding::PLAIN,
222 Encoding::RLE_DICTIONARY,
223 Encoding::DELTA_BYTE_ARRAY,
224 ] {
225 let mut page = PreparedFixedLenByteArrayPage {
226 encoding,
227 data: Bytes::from_static(b"abcdefghijkl"),
228 validate_count: false,
229 };
230 assert!(
231 !prepare_v1_page(&mut page, 3, 4, &|| {
232 panic!("ordinary page must not be pre-scanned")
233 })
234 .unwrap()
235 );
236 assert_eq!(page.encoding, encoding);
237 assert_eq!(page.data.as_ref(), b"abcdefghijkl");
238 assert!(!page.validate_count);
239 }
240 }
241
242 #[test]
243 fn matching_prefixes_require_an_independent_count() {
244 let calls = std::cell::Cell::new(0);
245 let raw = Bytes::from(4_u32.to_le_bytes().repeat(10));
246 let mut page = PreparedFixedLenByteArrayPage {
247 encoding: Encoding::PLAIN,
248 data: raw.clone(),
249 validate_count: false,
250 };
251 assert!(
252 prepare_v1_page(&mut page, 20, 4, &|| {
253 calls.set(calls.get() + 1);
254 Ok(10) })
256 .unwrap()
257 );
258 assert_eq!(calls.get(), 1);
259 assert_eq!(page.data, raw);
260 assert_eq!(page.encoding, Encoding::PLAIN);
261 assert!(!page.validate_count);
262
263 let mut malformed = 4_u32.to_le_bytes().repeat(12);
265 malformed[40..44].fill(0xff);
266 let mut reader = nullable_fixed_reader(vec![nullable_fixed_page(
267 &[1; 6],
268 Encoding::PLAIN,
269 &malformed,
270 )]);
271 let mut values = vec![];
272 assert!(
273 reader
274 .read_records(1, Some(&mut vec![]), None, &mut values)
275 .is_err()
276 );
277 assert!(values.is_empty());
278 }
279
280 #[test]
281 fn incremental_delta_length_count_validation() {
282 check_incremental_fixed_len_byte_array_pages(Encoding::DELTA_LENGTH_BYTE_ARRAY, |count| {
283 let mut lengths = DeltaBitPackEncoder::<Int32Type>::new();
284 lengths.put(&vec![4; count]).unwrap();
285 let mut payload = lengths.flush_buffer().unwrap().to_vec();
286 payload.extend_from_slice(&b"abcd".repeat(count));
287 payload
288 });
289
290 for lengths in [vec![], vec![4; 5], vec![3, 5]] {
291 let mut encoder = DeltaBitPackEncoder::<Int32Type>::new();
292 encoder.put(&lengths).unwrap();
293 let mut payload = encoder.flush_buffer().unwrap().to_vec();
294 payload.extend(std::iter::repeat_n(
295 b'x',
296 lengths.iter().sum::<i32>() as usize,
297 ));
298 let def = if lengths.is_empty() {
299 [0; 4]
300 } else {
301 [1, 0, 1, 0]
302 };
303 let mut reader = nullable_fixed_reader(vec![nullable_fixed_page(
304 &def,
305 Encoding::DELTA_LENGTH_BYTE_ARRAY,
306 &payload,
307 )]);
308 let result = reader.read_records(1, Some(&mut vec![]), None, &mut vec![]);
309 if lengths.is_empty() {
310 assert_eq!(result.unwrap(), (1, 0, 1));
311 assert_eq!(reader.skip_records(3).unwrap(), 3);
312 } else {
313 assert!(result.is_err());
315 }
316 }
317 }
318
319 #[test]
320 fn prefix_probe_only_rules_out_legacy() {
321 for width in [0, 1, 2, 3, 4, 16, 32] {
322 for count in [0, 1, 5, 6] {
323 let mut data = vec![];
324 for _ in 0..count {
325 data.extend_from_slice(&(width as u32).to_le_bytes());
326 data.extend(std::iter::repeat_n(0x55, width));
327 }
328 assert_eq!(may_be_length_prefixed_plain(&data, width), count != 0);
329 if !data.is_empty() {
330 let mut truncated = data.clone();
331 truncated.pop();
332 assert!(!may_be_length_prefixed_plain(&truncated, width));
333 data[0] ^= 1;
334 assert!(!may_be_length_prefixed_plain(&data, width));
335 }
336 }
337 }
338 assert!(!may_be_length_prefixed_plain(&[], usize::MAX));
339 let mut data = 4_u32.to_le_bytes().repeat(12);
340 data[40..44].fill(0xff);
341 assert!(may_be_length_prefixed_plain(&data, 4)); }
343
344 #[test]
345 fn length_prefixed_plain() {
346 let mut rng = StdRng::seed_from_u64(11261);
347 for page in ["dictionary page", "PLAIN data page"] {
348 for width in [0, 1, 4, 8, 16, 32] {
349 for count in [0, 1, 2, 33] {
350 let raw: Bytes = (0..width * count).map(|_| rng.random::<u8>()).collect();
351 let mut legacy = vec![];
352 for i in 0..count {
353 legacy.extend_from_slice(&(width as u32).to_le_bytes());
354 legacy.extend_from_slice(&raw[i * width..(i + 1) * width]);
355 }
356 assert_eq!(
357 normalize_fixed_len_byte_array_payload(legacy.into(), count, width, page)
358 .unwrap(),
359 raw
360 );
361 }
362 }
363 for data in [
365 b"\x03\0\0\0abc\x05\0\0\0defgh".as_slice(),
366 b"\x04\0\0\0abcd\xff\xff\xff\xffefgh",
367 b"\x04\0\0\0abcd\x04\0\0\0efg",
368 b"\x04\0\0\0abcd\x04\0\0\0efghi",
369 ] {
370 assert!(
371 normalize_fixed_len_byte_array_payload(
372 Bytes::copy_from_slice(data),
373 2,
374 4,
375 page,
376 )
377 .is_err()
378 );
379 }
380 }
381 }
382
383 #[test]
384 fn data_pages() {
385 let length_prefixed = |raw: &[u8]| {
386 let mut legacy = vec![];
387 for value in raw.as_chunks::<4>().0 {
388 legacy.extend_from_slice(&4_u32.to_le_bytes());
389 legacy.extend_from_slice(value);
390 }
391 legacy
392 };
393 super::super::tests::check_fixed_len_byte_array_pages(
394 |raw| {
395 let mut lengths = DeltaBitPackEncoder::<Int32Type>::new();
396 lengths.put(&vec![4; raw.len() / 4]).unwrap();
397 let mut delta = lengths.flush_buffer().unwrap().to_vec();
398 delta.extend_from_slice(raw);
399 vec![
400 (Encoding::PLAIN, length_prefixed(raw)),
401 (Encoding::DELTA_LENGTH_BYTE_ARRAY, delta),
402 ]
403 },
404 |raw| {
405 let mut bad_prefix = length_prefixed(raw);
406 if raw.is_empty() {
407 bad_prefix.extend_from_slice(&4_u32.to_le_bytes());
409 } else {
410 bad_prefix[0] = 3;
411 }
412 vec![bad_prefix]
413 },
414 );
415 }
416
417 #[test]
418 fn delta_length() {
419 let encode = |lengths: &[i32], values: &[u8]| {
420 let mut encoder = DeltaBitPackEncoder::<Int32Type>::new();
421 encoder.put(lengths).unwrap();
422 let mut data = encoder.flush_buffer().unwrap().to_vec();
423 data.extend_from_slice(values);
424 Bytes::from(data)
425 };
426 let normalize = |data, count| {
427 normalize_fixed_len_byte_array_data(data, count, 4, Encoding::DELTA_LENGTH_BYTE_ARRAY)
428 };
429 for count in [0, 1, 2, 129, 2051] {
430 let values = b"abcd".repeat(count);
431 let data = encode(&vec![4; count], &values);
432 let (encoding, result) = normalize(data.clone(), count).unwrap();
433 assert_eq!(encoding, Encoding::PLAIN);
434 assert_eq!(result.as_ref(), values);
435 assert_eq!(
436 result.as_ptr(),
437 data.as_ptr().wrapping_add(data.len() - result.len())
438 );
439 }
440 for (lengths, values, count) in [
441 (vec![3, 5], b"abcdefgh".as_slice(), 2),
442 (vec![4, -1], b"abcdefgh", 2),
443 (vec![4, 4], b"abcdefgh", 1),
444 (vec![4, 4], b"abcdefg", 2),
445 (vec![4, 4], b"abcdefghi", 2),
446 (vec![], b"x", 0),
447 ] {
448 assert!(normalize(encode(&lengths, values), count).is_err());
449 }
450 assert!(normalize(Bytes::new(), 1).is_err());
451 assert!(normalize(Bytes::new(), usize::MAX).is_err());
452 }
453}