Skip to main content

parquet/arrow/async_reader/
metadata.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use crate::arrow::async_reader::AsyncFileReader;
6use crate::errors::Result;
7use bytes::Bytes;
8use futures::future::BoxFuture;
9use std::ops::Range;
10
11/// A data source that can be used with [`ParquetMetaDataReader`] to load [`ParquetMetaData`]
12///
13/// Note that implementation is provided for [`AsyncFileReader`].
14///
15/// # Example `MetadataFetch` for a custom async data source
16///
17/// ```rust
18/// # use parquet::errors::Result;
19/// # use parquet::arrow::async_reader::MetadataFetch;
20/// # use bytes::Bytes;
21/// # use std::ops::Range;
22/// # use std::io::SeekFrom;
23/// # use futures::future::BoxFuture;
24/// # use futures::FutureExt;
25/// # use tokio::io::{AsyncReadExt, AsyncSeekExt};
26/// // Adapter that implements the API for reading bytes from an async source (in
27/// // this case a tokio::fs::File)
28/// struct TokioFileMetadata {
29///     file: tokio::fs::File,
30/// }
31/// impl MetadataFetch for TokioFileMetadata {
32///     fn fetch(&mut self, range: Range<u64>) -> BoxFuture<'_, Result<Bytes>> {
33///         // return a future that fetches data in range
34///         async move {
35///             let len = (range.end - range.start).try_into().unwrap();
36///             let mut buf = vec![0; len]; // target buffer
37///             // seek to the start of the range and read the data
38///             self.file.seek(SeekFrom::Start(range.start)).await?;
39///             self.file.read_exact(&mut buf).await?;
40///             Ok(Bytes::from(buf)) // convert to Bytes
41///         }
42///             .boxed() // turn into BoxedFuture, using FutureExt::boxed
43///     }
44/// }
45///```
46///
47/// [`ParquetMetaDataReader`]: crate::file::metadata::reader::ParquetMetaDataReader
48/// [`ParquetMetaData`]: crate::file::metadata::ParquetMetaData
49pub trait MetadataFetch {
50    /// Return a future that fetches the specified range of bytes asynchronously
51    ///
52    /// Note the returned type is a boxed future, often created by
53    /// [`FutureExt::boxed`]. See the trait documentation for an example
54    ///
55    /// [`FutureExt::boxed`]: futures::FutureExt::boxed
56    fn fetch(&mut self, range: Range<u64>) -> BoxFuture<'_, Result<Bytes>>;
57}
58
59impl<T: AsyncFileReader> MetadataFetch for &mut T {
60    fn fetch(&mut self, range: Range<u64>) -> BoxFuture<'_, Result<Bytes>> {
61        self.get_bytes(range)
62    }
63}
64
65/// A data source that can be used with [`ParquetMetaDataReader`] to load [`ParquetMetaData`] via suffix
66/// requests, without knowing the file size
67///
68/// [`ParquetMetaDataReader`]: crate::file::metadata::reader::ParquetMetaDataReader
69/// [`ParquetMetaData`]: crate::file::metadata::ParquetMetaData
70pub trait MetadataSuffixFetch: MetadataFetch {
71    /// Return a future that fetches the last `n` bytes asynchronously
72    ///
73    /// Note the returned type is a boxed future, often created by
74    /// [`FutureExt::boxed`]. See the trait documentation for an example
75    ///
76    /// [`FutureExt::boxed`]: futures::FutureExt::boxed
77    fn fetch_suffix(&mut self, suffix: usize) -> BoxFuture<'_, Result<Bytes>>;
78}