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