pub fn filter_chunks(mut self, pedantic: bool, mut filter: impl FnMut(&MetaData, TileCoordinates, BlockIndex) -> bool) -> Result<FilteredChunksReader<R>> {
        let offset_tables = MetaData::read_offset_tables(&mut self.remaining_reader, &self.meta_data.headers)?;

        // TODO regardless of pedantic, if invalid, read all chunks instead, and filter after reading each chunk?
        if pedantic {
            validate_offset_tables(
                self.meta_data.headers.as_slice(), &offset_tables,
                self.remaining_reader.byte_position()
            )?;
        }

        let mut filtered_offsets = Vec::with_capacity(
            (self.meta_data.headers.len() * 32).min(2*2048)
        );

        // TODO detect whether the filter actually would skip chunks, and aviod sorting etc when not filtering is applied

        for (header_index, header) in self.meta_data.headers.iter().enumerate() { // offset tables are stored same order as headers
            for (block_index, tile) in header.blocks_increasing_y_order().enumerate() { // in increasing_y order
                let data_indices = header.get_absolute_block_pixel_coordinates(tile.location)?;

                let block = BlockIndex {
                    layer: header_index,
                    level: tile.location.level_index,
                    pixel_position: data_indices.position.to_usize("data indices start")?,
                    pixel_size: data_indices.size,
                };

                if filter(&self.meta_data, tile.location, block) {
                    filtered_offsets.push(offset_tables[header_index][block_index]) // safe indexing from `enumerate()`
                }
            };
        }

        filtered_offsets.sort_unstable(); // enables reading continuously if possible (already sorted where line order increasing)

        if pedantic {
            // table is sorted. if any two neighbours are equal, we have duplicates. this is invalid.
            if filtered_offsets.windows(2).any(|pair| pair[0] == pair[1]) {
                return Err(Error::invalid("chunk offset table"))
            }
        }

        Ok(FilteredChunksReader {
            meta_data: self.meta_data,
            expected_filtered_chunk_count: filtered_offsets.len(),
            remaining_filtered_chunk_indices: filtered_offsets.into_iter(),
            remaining_bytes: self.remaining_reader
        })
    }
/// Prepare to read some the chunks from the file.
/// Does not decode the chunks now, but returns a decoder.
/// Reading only some chunks may seeking the file, potentially skipping many bytes.
// TODO tile indices add no new information to block index??
Prepare to read some the chunks from the file.
Does not decode the chunks now, but returns a decoder.
Reading only some chunks may seeking the file, potentially skipping many bytes.
Prepare to read some the chunks from the file . Does not decode the chunks now but returns a decoder . Reading only some chunks may seeking the file potentially skipping many bytes .
pub fn filter_chunks(mut self, pedantic: bool, mut filter: impl FnMut(&MetaData, TileCoordinates, BlockIndex) -> bool) -> Result<FilteredChunksReader<R>> {
        let offset_tables = MetaData::read_offset_tables(&mut self.remaining_reader, &self.meta_data.headers)?;
        // TODO regardless of pedantic, if invalid, read all chunks instead, and filter after reading each chunk?
        if pedantic {
            validate_offset_tables(
                self.meta_data.headers.as_slice(), &offset_tables,
                self.remaining_reader.byte_position()
            )?;
        }
        let mut filtered_offsets = Vec::with_capacity(
            (self.meta_data.headers.len() * 32).min(2*2048)
        );
        // TODO detect whether the filter actually would skip chunks, and aviod sorting etc when not filtering is applied
        for (header_index, header) in self.meta_data.headers.iter().enumerate() { // offset tables are stored same order as headers
            for (block_index, tile) in header.blocks_increasing_y_order().enumerate() { // in increasing_y order
                let data_indices = header.get_absolute_block_pixel_coordinates(tile.location)?;
                let block = BlockIndex {
                    layer: header_index,
                    level: tile.location.level_index,
                    pixel_position: data_indices.position.to_usize("data indices start")?,
                    pixel_size: data_indices.size,
                };
                if filter(&self.meta_data, tile.location, block) {
                    filtered_offsets.push(offset_tables[header_index][block_index]) // safe indexing from `enumerate()`
                }
            };
        }
        filtered_offsets.sort_unstable(); // enables reading continuously if possible (already sorted where line order increasing)
        if pedantic {
            // table is sorted. if any two neighbours are equal, we have duplicates. this is invalid.
            if filtered_offsets.windows(2).any(|pair| pair[0] == pair[1]) {
                return Err(Error::invalid("chunk offset table"))
            }
        }
        Ok(FilteredChunksReader {
            meta_data: self.meta_data,
            expected_filtered_chunk_count: filtered_offsets.len(),
            remaining_filtered_chunk_indices: filtered_offsets.into_iter(),
            remaining_bytes: self.remaining_reader
        })
    }
pub fn filter_chunks ( mut self , pedantic : bool , mut filter : impl FnMut ( & MetaData , TileCoordinates , BlockIndex ) -> bool ) -> Result < FilteredChunksReader < R > > { let offset_tables = MetaData :: read_offset_tables ( & mut self . remaining_reader , & self . meta_data . headers ) ? ; // TODO regardless of pedantic, if invalid, read all chunks instead, and filter after reading each chunk? if pedantic { validate_offset_tables ( self . meta_data . headers . as_slice ( ) , & offset_tables , self . remaining_reader . byte_position ( ) ) ? ; } let mut filtered_offsets = Vec :: with_capacity ( ( self . meta_data . headers . len ( ) * 32 ) . min ( 2 * 2048 ) ) ; // TODO detect whether the filter actually would skip chunks, and aviod sorting etc when not filtering is applied for ( header_index , header ) in self . meta_data . headers . iter ( ) . enumerate ( ) { // offset tables are stored same order as headers for ( block_index , tile ) in header . blocks_increasing_y_order ( ) . enumerate ( ) { // in increasing_y order let data_indices = header . get_absolute_block_pixel_coordinates ( tile . location ) ? ; let block = BlockIndex { layer : header_index , level : tile . location . level_index , pixel_position : data_indices . position . to_usize ( " " ) ? , pixel_size : data_indices . size , } ; if filter ( & self . meta_data , tile . location , block ) { filtered_offsets . push ( offset_tables [ header_index ] [ block_index ] ) // safe indexing from `enumerate()` } } ; } filtered_offsets . sort_unstable ( ) ; // enables reading continuously if possible (already sorted where line order increasing) if pedantic { // table is sorted. if any two neighbours are equal, we have duplicates. this is invalid. if filtered_offsets . windows ( 2 ) . any ( | pair | pair [ 0 ] == pair [ 1 ] ) { return Err ( Error :: invalid ( " " ) ) } } Ok ( FilteredChunksReader { meta_data : self . meta_data , expected_filtered_chunk_count : filtered_offsets . len ( ) , remaining_filtered_chunk_indices : filtered_offsets . into_iter ( ) , remaining_bytes : self . remaining_reader } ) }
Prepare to read some the chunks from the file.
Prepare to read some the chunks from the file .
mut self
pedantic
bool
filter
impl FnMut(&MetaData, TileCoordinates, BlockIndex) -> bool
mut self
pedantic
bool
filter
impl FnMut(&MetaData, TileCoordinates, BlockIndex) -> bool