Calculates an appropriate byte range for reading from an object based on the provided metadata. This asynchronous function examines the [`PartitionedFile`] of an object in an object store and determines the range of bytes to be read. The range calculation may adjust the start and end points to align with meaningful data boundaries (like newlines). Returns a `Result` wrapping a [`RangeCalculation
(
file: &PartitionedFile,
store: &Arc<dyn ObjectStore>,
terminator: Option<u8>,
)
| 416 | /// |
| 417 | /// Returns an `Error` if any part of the range calculation fails, such as issues in reading from the object store or invalid range boundaries. |
| 418 | pub async fn calculate_range( |
| 419 | file: &PartitionedFile, |
| 420 | store: &Arc<dyn ObjectStore>, |
| 421 | terminator: Option<u8>, |
| 422 | ) -> Result<RangeCalculation> { |
| 423 | let location = &file.object_meta.location; |
| 424 | let file_size = file.object_meta.size; |
| 425 | let newline = terminator.unwrap_or(b'\n'); |
| 426 | |
| 427 | match file.range { |
| 428 | None => Ok(RangeCalculation::Range(None)), |
| 429 | Some(FileRange { start, end }) => { |
| 430 | let start: u64 = start.try_into().map_err(|_| { |
| 431 | exec_datafusion_err!("Expect start range to fit in u64, got {start}") |
| 432 | })?; |
| 433 | let end: u64 = end.try_into().map_err(|_| { |
| 434 | exec_datafusion_err!("Expect end range to fit in u64, got {end}") |
| 435 | })?; |
| 436 | |
| 437 | let start_delta = if start != 0 { |
| 438 | find_first_newline(store, location, start - 1, file_size, newline).await? |
| 439 | } else { |
| 440 | 0 |
| 441 | }; |
| 442 | |
| 443 | if start + start_delta > end { |
| 444 | return Ok(RangeCalculation::TerminateEarly); |
| 445 | } |
| 446 | |
| 447 | let end_delta = if end != file_size { |
| 448 | find_first_newline(store, location, end - 1, file_size, newline).await? |
| 449 | } else { |
| 450 | 0 |
| 451 | }; |
| 452 | |
| 453 | let range = start + start_delta..end + end_delta; |
| 454 | |
| 455 | if range.start >= range.end { |
| 456 | return Ok(RangeCalculation::TerminateEarly); |
| 457 | } |
| 458 | |
| 459 | Ok(RangeCalculation::Range(Some(range))) |
| 460 | } |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | /// Asynchronously finds the position of the first newline character in a specified byte range |
| 465 | /// within an object, such as a file, in an object store. |
searching dependent graphs…