Export a change from redb to V3 bytes in memory. This is the core export method used by both file export and network transfer.
(&self, hash: &[u8; 32])
| 375 | /// This is the core export method used by both file export and |
| 376 | /// network transfer. |
| 377 | pub fn export_v3_bytes(&self, hash: &[u8; 32]) -> RedbStoreResult<Vec<u8>> { |
| 378 | let meta = self.load_meta(hash)?; |
| 379 | |
| 380 | // Reconstruct the hash dedup table |
| 381 | let hash_table = if meta.hash_table.is_empty() { |
| 382 | HashDedupTable::empty() |
| 383 | } else { |
| 384 | HashDedupTable::from_hashes(meta.hash_table.clone()).map_err(|e| { |
| 385 | RedbStoreError::Corrupt(format!("hash table reconstruction failed: {}", e)) |
| 386 | })? |
| 387 | }; |
| 388 | |
| 389 | // Build file header |
| 390 | let mut file_header_builder = FileHeader::builder() |
| 391 | .hash_table_entries(hash_table.len() as u32) |
| 392 | .graph_section_count(meta.graph_section_count) |
| 393 | .semantic_section_count(meta.semantic_section_count) |
| 394 | .contents_chunks(meta.content_chunk_count); |
| 395 | |
| 396 | if meta.has_provenance { |
| 397 | file_header_builder = file_header_builder.with_provenance(); |
| 398 | } |
| 399 | if meta.has_unhashed { |
| 400 | file_header_builder = file_header_builder.with_unhashed(); |
| 401 | } |
| 402 | |
| 403 | let file_header = file_header_builder.build(); |
| 404 | |
| 405 | // Write V3 format |
| 406 | let mut output = Vec::new(); |
| 407 | let mut writer = ChangeWriter::new(&mut output, WriterOptions::default()); |
| 408 | |
| 409 | writer.write_file_header(&file_header)?; |
| 410 | writer.write_hash_table(&hash_table)?; |
| 411 | |
| 412 | // Write HEADER section |
| 413 | writer.write_change_header(&meta.header)?; |
| 414 | |
| 415 | // Write DEPS section |
| 416 | writer.write_dependencies(&meta.dependency_indices)?; |
| 417 | |
| 418 | // Write GRAPH sections |
| 419 | let txn = self.db().begin_read()?; |
| 420 | { |
| 421 | let graph_table = txn.open_table(tables::CHANGE_GRAPH)?; |
| 422 | for idx in 0..meta.graph_section_count { |
| 423 | let key = tables::encode_change_file_key(hash, idx); |
| 424 | if let Some(value) = graph_table.get(&key)? { |
| 425 | let compressed = value.value(); |
| 426 | let decompressed = zstd::decode_all(compressed).map_err(|e| { |
| 427 | RedbStoreError::Corrupt(format!( |
| 428 | "graph section {} decompression failed: {}", |
| 429 | idx, e |
| 430 | )) |
| 431 | })?; |
| 432 | writer.write_graph_section(&decompressed)?; |
| 433 | } |
| 434 | } |