heddle_object_model/compact/
extract.rs1use super::{CompactError, Result, decode_state_frame};
4use crate::object::{State, StateId};
5
6pub fn extract_state(bytes: &[u8], expected: StateId) -> Result<State> {
12 decode_state_frame(bytes)?
13 .into_iter()
14 .find(|state| state.accepts_stored_id(&expected))
15 .map(|mut state| {
16 state.state_id = expected;
17 state
18 })
19 .ok_or(CompactError::Missing)
20}
21
22#[cfg(test)]
23mod tests {
24 use std::time::Instant;
25
26 use super::super::{decode_tree_frame, encode_tree_frame, extract_tree};
27 use crate::object::{ContentHash, Tree, TreeEntry};
28
29 #[test]
30 fn extract_tree_point_read_beats_decode_all_and_serialize() {
31 let trees = (0..64)
32 .map(|index| {
33 Tree::from_entries(vec![
34 TreeEntry::file(
35 format!("file-{index}.txt"),
36 ContentHash::from_bytes([index as u8; 32]),
37 false,
38 )
39 .unwrap(),
40 ])
41 })
42 .collect::<Vec<_>>();
43 let encoded = encode_tree_frame(&trees).unwrap();
44 let first = trees[0].hash();
45 let last = trees[trees.len() - 1].hash();
46 let _ = extract_tree(&encoded, first).unwrap();
47 let _ = decode_tree_frame(&encoded).unwrap();
48
49 const ITERATIONS: u32 = 200;
50 let start = Instant::now();
51 for _ in 0..ITERATIONS {
52 let decoded = decode_tree_frame(&encoded).unwrap();
53 let _ = decoded
54 .into_iter()
55 .map(|tree| rmp_serde::to_vec_named(&tree).unwrap())
56 .collect::<Vec<_>>();
57 }
58 let decode_all = start.elapsed();
59
60 let start = Instant::now();
61 for _ in 0..ITERATIONS {
62 let tree = extract_tree(&encoded, first).unwrap();
63 let _ = rmp_serde::to_vec_named(&tree).unwrap();
64 }
65 let extract_first = start.elapsed();
66
67 let start = Instant::now();
68 for _ in 0..ITERATIONS {
69 let tree = extract_tree(&encoded, last).unwrap();
70 let _ = rmp_serde::to_vec_named(&tree).unwrap();
71 }
72 let extract_last = start.elapsed();
73
74 eprintln!(
75 "compact tree frame (64 trees, {ITERATIONS} iters): decode-all+serialize-all {decode_all:?}; extract-first {extract_first:?}; extract-last {extract_last:?}"
76 );
77 assert!(
78 extract_first < decode_all && extract_last < decode_all,
79 "single-object extract should beat decode-all, first={extract_first:?} last={extract_last:?} decode_all={decode_all:?}"
80 );
81 }
82}