Decode a single block by index without decoding the entire stream. Iterates block headers to reach `block_idx`, then decodes only that block. For sequential block-at-a-time processing, prefer [`BlockIterator`] which tracks byte offsets without re-scanning.
(data: &[u8], block_idx: usize)
| 174 | /// block. For sequential block-at-a-time processing, prefer |
| 175 | /// [`BlockIterator`] which tracks byte offsets without re-scanning. |
| 176 | pub fn decode_single_block(data: &[u8], block_idx: usize) -> Result<Vec<i64>, CodecError> { |
| 177 | if data.len() < GLOBAL_HEADER_SIZE { |
| 178 | return Err(CodecError::Truncated { |
| 179 | expected: GLOBAL_HEADER_SIZE, |
| 180 | actual: data.len(), |
| 181 | }); |
| 182 | } |
| 183 | let num_blocks = u16::from_le_bytes([data[4], data[5]]) as usize; |
| 184 | if block_idx >= num_blocks { |
| 185 | return Err(CodecError::Corrupt { |
| 186 | detail: format!("block_idx {block_idx} >= block_count {num_blocks}"), |
| 187 | }); |
| 188 | } |
| 189 | |
| 190 | // Skip to the target block by iterating headers. |
| 191 | let mut offset = GLOBAL_HEADER_SIZE; |
| 192 | for i in 0..block_idx { |
| 193 | offset = skip_block(data, offset, i)?; |
| 194 | } |
| 195 | |
| 196 | let mut values = Vec::new(); |
| 197 | decode_block(data, offset, &mut values, block_idx)?; |
| 198 | Ok(values) |
| 199 | } |
| 200 | |
| 201 | /// Iterator that decodes one 1024-row block at a time, tracking byte |
| 202 | /// offsets internally. Avoids re-scanning headers for sequential access. |