(
&mut self,
output: &mut ViewBuffer,
len: usize,
)
| 326 | } |
| 327 | |
| 328 | fn read_impl<const VALIDATE_UTF8: bool>( |
| 329 | &mut self, |
| 330 | output: &mut ViewBuffer, |
| 331 | len: usize, |
| 332 | ) -> Result<usize> { |
| 333 | // avoid creating a new buffer if the last buffer is the same as the current buffer |
| 334 | // This is especially useful when row-level filtering is applied, where we call lots of small `read` over the same buffer. |
| 335 | let block_id = { |
| 336 | if output.buffers.last().is_some_and(|x| x.ptr_eq(&self.buf)) { |
| 337 | output.buffers.len() as u32 - 1 |
| 338 | } else { |
| 339 | output.append_block(self.buf.clone()) |
| 340 | } |
| 341 | }; |
| 342 | |
| 343 | let to_read = len.min(self.max_remaining_values); |
| 344 | |
| 345 | let buf: &[u8] = self.buf.as_ref(); |
| 346 | let buf_len = buf.len(); |
| 347 | let mut end_offset = self.offset; |
| 348 | let mut utf8_validation_begin = end_offset; |
| 349 | |
| 350 | output.views.reserve(to_read); |
| 351 | |
| 352 | // Safety: we reserved enough space in output.views |
| 353 | // and we will only write up to to_read views / track how many views we wrote. |
| 354 | // Ideally, we would use `Vec::extend` here, but this generates sub-optimal code. |
| 355 | let views_ptr = output.views.as_mut_ptr().wrapping_add(output.views.len()); |
| 356 | for i in 0..to_read { |
| 357 | let start_offset = end_offset + 4; |
| 358 | |
| 359 | if start_offset > buf_len { |
| 360 | return Err(ParquetError::EOF("eof decoding byte array".into())); |
| 361 | } |
| 362 | |
| 363 | // Safety: we have checked that start_offset <= buf_len |
| 364 | let len = u32::from_le_bytes( |
| 365 | unsafe { buf.get_unchecked(end_offset..start_offset) } |
| 366 | .try_into() |
| 367 | .unwrap(), |
| 368 | ); |
| 369 | |
| 370 | end_offset = start_offset + len as usize; |
| 371 | |
| 372 | if end_offset > buf_len { |
| 373 | return Err(ParquetError::EOF("eof decoding byte array".into())); |
| 374 | } |
| 375 | |
| 376 | if VALIDATE_UTF8 { |
| 377 | // It seems you are trying to understand what's going on here, take a breath and be patient. |
| 378 | // Utf-8 validation is a non-trivial task, here are some background facts: |
| 379 | // (1) Validating one 2048-byte string is much faster than validating 128 of 16-byte string. |
| 380 | // As shown in https://github.com/apache/arrow-rs/pull/6009#issuecomment-2211174229 |
| 381 | // Potentially because the SIMD operations favor longer strings. |
| 382 | // (2) Practical strings are short, 99% of strings are smaller than 100 bytes, as shown in paper: |
| 383 | // https://www.vldb.org/pvldb/vol17/p148-zeng.pdf, Figure 5f. |
| 384 | // (3) Parquet plain encoding makes utf-8 validation harder, |
| 385 | // because it stores the length of each string right before the string. |
nothing calls this directly
no test coverage detected