state_tree/patch.rs
1/// A patch to be applied to a flat state storage from old storage.
2///
3/// A patch represents a flat array copy operation from the source data storage
4/// to the destination data storage.
5#[derive(Debug, PartialEq, Eq, Clone, Hash)]
6pub struct CopyFromPatch {
7 /// Starting address in the source data storage (index from the beginning of the array)
8 pub src_addr: usize,
9 /// Starting address in the destination data storage
10 pub dst_addr: usize,
11 /// Size of data to copy (in u64 units)
12 pub size: usize,
13}
14
15/// Apply patches to a new flat array.
16///
17/// # Arguments
18/// * `new_storage` - Destination flat array with the new structure (initialized with zeros)
19/// * `old_storage` - Source flat array with the old structure
20/// * `patches` - List of patches generated by the `diff` function
21///
22/// # Panics
23/// May panic if the addresses or sizes in the patches are invalid.
24/// (This should not happen if `diff` is correctly implemented)
25pub fn apply_patches(new_storage: &mut [u64], old_storage: &[u64], patches: &[CopyFromPatch]) {
26 for patch in patches {
27 let src_end = patch.src_addr + patch.size;
28 let dst_end = patch.dst_addr + patch.size;
29
30 debug_assert!(
31 src_end <= old_storage.len(),
32 "Source address range [{}, {}) exceeds old storage size {}",
33 patch.src_addr,
34 src_end,
35 old_storage.len()
36 );
37 debug_assert!(
38 dst_end <= new_storage.len(),
39 "Destination address range [{}, {}) exceeds new storage size {}",
40 patch.dst_addr,
41 dst_end,
42 new_storage.len()
43 );
44
45 // Perform flat array copy
46 new_storage[patch.dst_addr..dst_end]
47 .copy_from_slice(&old_storage[patch.src_addr..src_end]);
48 }
49}