1pub mod patch;
2pub mod tree;
3pub mod tree_diff;
4
5use crate::patch::CopyFromPatch;
6use crate::tree::{SizedType, StateTreeSkeleton};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct StateStoragePatchPlan {
10 pub total_size: usize,
11 pub patches: Vec<CopyFromPatch>,
12}
13
14pub fn build_state_storage_patch_plan<T: SizedType + PartialEq>(
15 old_state_skeleton: StateTreeSkeleton<T>,
16 new_state_skeleton: StateTreeSkeleton<T>,
17) -> Option<StateStoragePatchPlan> {
18 if old_state_skeleton == new_state_skeleton {
19 return None;
20 }
21
22 let total_size = new_state_skeleton.total_size() as usize;
23 let patches = tree_diff::take_diff(&old_state_skeleton, &new_state_skeleton)
24 .into_iter()
25 .collect::<Vec<_>>();
26
27 Some(StateStoragePatchPlan {
28 total_size,
29 patches,
30 })
31}
32
33pub fn apply_state_storage_patch_plan(
34 old_storage: &[u64],
35 patch_plan: &StateStoragePatchPlan,
36) -> Vec<u64> {
37 let mut new_storage = vec![0u64; patch_plan.total_size];
38 patch::apply_patches(&mut new_storage, old_storage, patch_plan.patches.as_slice());
39
40 debug_assert_eq!(new_storage.len(), patch_plan.total_size);
41
42 new_storage
43}
44
45pub fn update_state_storage<T: SizedType + PartialEq>(
46 old: &[u64],
47 old_state_skeleton: StateTreeSkeleton<T>,
48 new_state_skeleton: StateTreeSkeleton<T>,
49) -> Result<Option<Vec<u64>>, Box<dyn std::error::Error>> {
50 let patch_plan = build_state_storage_patch_plan(old_state_skeleton, new_state_skeleton);
51 if let Some(plan) = patch_plan {
52 for patch in &plan.patches {
53 log::debug!("Patch: {patch:?}");
54 }
55
56 Ok(Some(apply_state_storage_patch_plan(old, &plan)))
57 } else {
58 Ok(None)
59 }
60}