pub struct SbbfPushDecoder {
state: DecodeState,
offset: u64,
length: Option<usize>,
buffers: PushBuffers,
}Expand description
Decodes a Bloom filter from caller-provided file ranges, without performing I/O.
The metadata and pushed bytes must refer to the same file. Ranges use absolute
file offsets. Call Self::try_decode to discover which ranges are needed,
then supply them using Self::push_range or Self::push_ranges. Bytes may
also be pushed in advance to avoid requests for already-buffered data.
Each requested range must be contained in a single pushed buffer; adjacent
buffers are not coalesced. After an error from Self::try_decode, discard
the decoder.
§Example
use bytes::Bytes;
use parquet::DecodeResult;
use parquet::bloom_filter::{Sbbf, SbbfPushDecoder};
use parquet::errors::Result;
use parquet::file::metadata::ColumnChunkMetaData;
fn decode_filter(metadata: &ColumnChunkMetaData, file_bytes: Bytes) -> Result<Option<Sbbf>> {
let Some(mut decoder) = SbbfPushDecoder::try_new(metadata)? else {
return Ok(None);
};
loop {
match decoder.try_decode()? {
DecodeResult::NeedsData(ranges) => {
let buffers = ranges.iter().map(|range| {
file_bytes.slice(range.start as usize..range.end as usize)
}).collect();
decoder.push_ranges(ranges, buffers)?;
}
DecodeResult::Data(filter) => return Ok(Some(filter)),
DecodeResult::Finished => unreachable!("filter was returned above"),
}
}
}
let filter = decode_filter(&metadata, file_bytes)?.unwrap();
assert!(filter.check("present"));Fields§
§state: DecodeStateDecoding state
offset: u64Offset of the Bloom filter in the file
length: Option<usize>Length of the Bloom filter
buffers: PushBuffersUnderlying buffers
Implementations§
Source§impl SbbfPushDecoder
impl SbbfPushDecoder
Sourcepub fn try_new(column_metadata: &ColumnChunkMetaData) -> Result<Option<Self>>
pub fn try_new(column_metadata: &ColumnChunkMetaData) -> Result<Option<Self>>
Create a new Bloom filter decoder for the given column chunk.
Returns None if the column chunk has no Bloom filter offset.
Invalid offsets and nonpositive advertised lengths return an error.
Sourcepub fn push_range(&mut self, range: Range<u64>, buffer: Bytes) -> Result<()>
pub fn push_range(&mut self, range: Range<u64>, buffer: Bytes) -> Result<()>
Pushes a file range into the decoder’s buffer.
Returns an error if the buffer length differs from the range length or decoding has finished.
Sourcepub fn push_ranges(
&mut self,
ranges: Vec<Range<u64>>,
buffers: Vec<Bytes>,
) -> Result<()>
pub fn push_ranges( &mut self, ranges: Vec<Range<u64>>, buffers: Vec<Bytes>, ) -> Result<()>
Pushes multiple file ranges into the decoder’s buffer.
The number of ranges must match the number of buffers, and each buffer must have the same length as its range. Pushing after decoding has finished returns an error.
Sourcefn get_bytes(&self, range: &Range<u64>) -> Result<Bytes>
fn get_bytes(&self, range: &Range<u64>) -> Result<Bytes>
Returns the bytes for the given range from the internal buffer
Sourcepub fn try_decode(&mut self) -> Result<DecodeResult<Sbbf>>
pub fn try_decode(&mut self) -> Result<DecodeResult<Sbbf>>
Attempts to decode the filter, returning the file ranges needed if data is missing. Repeated calls before supplying data return the same ranges.
Without prefetched data, requests one range when bloom_filter_length is
known, or two otherwise (a 20-byte header estimate, then the bitset).
Headers larger than the estimate require an advertised length.
After returning DecodeResult::Data, subsequent calls return
DecodeResult::Finished.
The state transitions can be visualized as:
┌──────────────┐
│ FindingRange │
└──────────────┘
│
choose initial range
│
▼
┌───────────────────┐ ───┐ bytes missing:
│ ReadingSbbfHeader │ │ return NeedsData(range),
└───────────────────┘ ◀──┘ wait for push_range(s)
│ │
length known length unknown
│ │
│ ▼
│ ┌───────────────────┐ ───┐ bytes missing:
│ │ ReadingSbbfBitset │ │ return NeedsData(range),
│ └───────────────────┘ ◀──┘ wait for push_range(s)
│ │
└───────┬───────┘
│
return Data(Sbbf)
│
▼
┌──────────┐ ───┐
│ Finished │ │ return Finished
└──────────┘ ◀──┘In the above:
- The initial range is the whole filter when its length is known, otherwise a 20-byte header prefix.
- Transitions proceed within the same
try_decode()call while the required bytes are buffered; push_range(s) supplies bytes without changing state. - Header parsing/validation must succeed before advancing. Any decoding error leaves the decoder unusable.