1use crate::{rstd::vec::Vec, RecordedForKey, TrieAccess, TrieHash, TrieLayout, TrieRecorder};
18use hashbrown::HashMap;
19
20#[cfg_attr(feature = "std", derive(Debug))]
22#[derive(PartialEq, Eq, Clone)]
23pub struct Record<HO> {
24 pub hash: HO,
26 pub data: Vec<u8>,
28}
29
30#[cfg_attr(feature = "std", derive(Debug))]
32pub struct Recorder<L: TrieLayout> {
33 nodes: Vec<Record<TrieHash<L>>>,
34 recorded_keys: HashMap<Vec<u8>, RecordedForKey>,
35}
36
37impl<L: TrieLayout> Default for Recorder<L> {
38 fn default() -> Self {
39 Recorder::new()
40 }
41}
42
43impl<L: TrieLayout> Recorder<L> {
44 pub fn new() -> Self {
46 Self { nodes: Default::default(), recorded_keys: Default::default() }
47 }
48
49 pub fn drain(&mut self) -> Vec<Record<TrieHash<L>>> {
51 self.recorded_keys.clear();
52 crate::rstd::mem::take(&mut self.nodes)
53 }
54}
55
56impl<L: TrieLayout> TrieRecorder<TrieHash<L>> for Recorder<L> {
57 fn record<'a>(&mut self, access: TrieAccess<'a, TrieHash<L>>) {
58 match access {
59 TrieAccess::EncodedNode { hash, encoded_node, .. } => {
60 self.nodes.push(Record { hash, data: encoded_node.to_vec() });
61 },
62 TrieAccess::NodeOwned { hash, node_owned, .. } => {
63 self.nodes.push(Record { hash, data: node_owned.to_encoded::<L::Codec>() });
64 },
65 TrieAccess::Value { hash, value, full_key } => {
66 self.nodes.push(Record { hash, data: value.to_vec() });
67 self.recorded_keys.entry(full_key.to_vec()).insert(RecordedForKey::Value);
68 },
69 TrieAccess::Hash { full_key } => {
70 self.recorded_keys.entry(full_key.to_vec()).or_insert(RecordedForKey::Hash);
71 },
72 TrieAccess::NonExisting { full_key } => {
73 self.recorded_keys.entry(full_key.to_vec()).insert(RecordedForKey::Value);
75 },
76 }
77 }
78
79 fn trie_nodes_recorded_for_key(&self, key: &[u8]) -> RecordedForKey {
80 self.recorded_keys.get(key).copied().unwrap_or(RecordedForKey::None)
81 }
82}