Load all content chunks for a change, in order. Reads from CHANGE_CHUNKS (manifest) + CONTENT_CHUNKS (data). Decompresses each chunk and returns the raw content. # Returns A vector of decompressed content chunks, ordered by chunk index.
(&self, hash: &[u8; 32])
| 170 | /// |
| 171 | /// A vector of decompressed content chunks, ordered by chunk index. |
| 172 | pub fn load_content_chunks(&self, hash: &[u8; 32]) -> RedbStoreResult<Vec<StoredContentChunk>> { |
| 173 | let meta = self.load_meta(hash)?; |
| 174 | let txn = self.db().begin_read()?; |
| 175 | let manifest_table = txn.open_table(tables::CHANGE_CHUNKS)?; |
| 176 | let content_table = txn.open_table(tables::CONTENT_CHUNKS)?; |
| 177 | |
| 178 | let mut chunks = Vec::with_capacity(meta.content_chunk_count as usize); |
| 179 | |
| 180 | for idx in 0..meta.content_chunk_count { |
| 181 | let manifest_key = tables::encode_change_file_key(hash, idx); |
| 182 | |
| 183 | if let Some(chunk_hash_value) = manifest_table.get(&manifest_key)? { |
| 184 | let chunk_hash = *chunk_hash_value.value(); |
| 185 | |
| 186 | if let Some(chunk_data_value) = content_table.get(&chunk_hash)? { |
| 187 | let compressed = chunk_data_value.value(); |
| 188 | let decompressed = zstd::decode_all(compressed).map_err(|e| { |
| 189 | RedbStoreError::Corrupt(format!( |
| 190 | "content chunk {} decompression failed: {}", |
| 191 | idx, e |
| 192 | )) |
| 193 | })?; |
| 194 | |
| 195 | chunks.push(StoredContentChunk { |
| 196 | index: idx, |
| 197 | hash: chunk_hash, |
| 198 | data: decompressed, |
| 199 | }); |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | Ok(chunks) |
| 205 | } |
| 206 | |
| 207 | /// Load the full content blob for a change by concatenating all chunks. |
| 208 | /// |