You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: state_parts.rs
    path of file: ./repos/nearcore/core/store/src/trie
    
    the code of the file until where you have to start completion: //! Logic for splitting state defined by `Trie` into parts.
//!
//! Needed when a node wants to download state from scratch. Single shard state size
//! is on the order of GBs, and state part size is expected to be on the order of MBs.
//!
//! State partition is defined using DFS traversal of trie. All parts are disjoint and
//! contiguous in this order. Left boundary of i-th part is determined by computing
//! prefix sums of memory usages of nodes.
//! A bit more precisely - memory usage threshold for i-th part is approximately
//! `total_size / num_parts * part_id`. The boundary itself is a first node which
//! corresponds to some key-value pair and prefix memory usage for it is greater
//! than a threshold.
//!
//! We include paths from root to both boundaries in state parts, because they are
//! necessary for receiver to prove existence of all nodes knowing just a state root.
//! Moreover, we include all left siblings for ea
    
    fn test_combine_state_parts() {
        let mut rng = rand::thread_rng();
        for _ in 0..2000 {
            let tries = TestTriesBuilder::new().build();
            let trie_changes = gen_changes(&mut rng, 20);
            let state_root = test_populate_trie(
                &tries,
                &Trie::EMPTY_ROOT,
                ShardUId::single_shard(),
                trie_changes.clone(),
            );
            let trie = tries.get_trie_for_shard(ShardUId::single_shard(), state_root);
            let root_memory_usage = trie.retrieve_root_node().unwrap().memory_usage;
            {
                // Test that combining all parts gets all nodes
                let num_parts = rng.gen_range(2..10);
                let parts = (0..num_parts)
                    .map(|part_id| {
                        trie.get_trie_nodes_for_part_without_flat_storage(PartId::new(
                            part_id, num_parts,
                        ))
                        .unwrap()
                    })
                    .collect::<Vec<_>>();

                let trie_changes = check_combine_state_parts(trie.get_root(), num_parts, &parts);

                let mut nodes = <HashMap<CryptoHash, Arc<[u8]>>>::new();
                let sizes_vec = parts
                    .iter()
                    .map(|PartialState::TrieValues(nodes)| {
                        nodes.iter().map(|node| node.len()).sum::<usize>()
                    })
                    .collect::<Vec<_>>();

                for part in parts {
                    let PartialState::TrieValues(part_nodes) = part;
                    for node in part_nodes {
                        nodes.insert(hash(&node), node);
                    }
                }
                let all_nodes = nodes.into_iter().map(|(_hash, node)| node).collect::<Vec<_>>();
                assert_eq!(all_nodes.len(), trie_changes.insertions.len());
                let size_of_all = all_nodes.iter().map(|node| node.len()).sum::<usize>();
                let num_nodes = all_nodes.len();
                assert_eq!(
                    Trie::validate_state_part(
                        trie.get_root(),
                        PartId::new(0, 1),
                        PartialState::TrieValues(all_nodes),
                    ),
                    Ok(())
                );

                let sum_of_sizes = sizes_vec.iter().sum::<usize>();
                // Manually check that sizes are reasonable
                println!("------------------------------");
                println!("Number of nodes: {:?}", num_nodes);
                println!("Sizes of parts: {:?}", sizes_vec);
                println!(
                    "All nodes size: {:?}, sum_of_sizes: {:?}, memory_usage: {:?}",
                    size_of_all, sum_of_sizes, root_memory_usage
                );
                // borsh serialize should be about this size
                assert!(size_of_all + 8 * num_nodes <= root_memory_usage as usize);
            }
        }
    }