use crate::{rstd::vec::Vec, RecordedForKey, TrieAccess, TrieHash, TrieLayout, TrieRecorder};
use hashbrown::HashMap;
#[cfg_attr(feature = "std", derive(Debug))]
#[derive(PartialEq, Eq, Clone)]
pub struct Record<HO> {
pub hash: HO,
pub data: Vec<u8>,
}
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Recorder<L: TrieLayout> {
nodes: Vec<Record<TrieHash<L>>>,
recorded_keys: HashMap<Vec<u8>, RecordedForKey>,
}
impl<L: TrieLayout> Default for Recorder<L> {
fn default() -> Self {
Recorder::new()
}
}
impl<L: TrieLayout> Recorder<L> {
pub fn new() -> Self {
Self { nodes: Default::default(), recorded_keys: Default::default() }
}
pub fn drain(&mut self) -> Vec<Record<TrieHash<L>>> {
self.recorded_keys.clear();
crate::rstd::mem::take(&mut self.nodes)
}
}
impl<L: TrieLayout> TrieRecorder<TrieHash<L>> for Recorder<L> {
fn record<'a>(&mut self, access: TrieAccess<'a, TrieHash<L>>) {
match access {
TrieAccess::EncodedNode { hash, encoded_node, .. } => {
self.nodes.push(Record { hash, data: encoded_node.to_vec() });
},
TrieAccess::NodeOwned { hash, node_owned, .. } => {
self.nodes.push(Record { hash, data: node_owned.to_encoded::<L::Codec>() });
},
TrieAccess::Value { hash, value, full_key } => {
self.nodes.push(Record { hash, data: value.to_vec() });
self.recorded_keys.entry(full_key.to_vec()).insert(RecordedForKey::Value);
},
TrieAccess::Hash { full_key } => {
self.recorded_keys.entry(full_key.to_vec()).or_insert(RecordedForKey::Hash);
},
TrieAccess::NonExisting { full_key } => {
self.recorded_keys.entry(full_key.to_vec()).insert(RecordedForKey::None);
},
TrieAccess::InlineValue { full_key } => {
self.recorded_keys.entry(full_key.to_vec()).insert(RecordedForKey::Value);
},
}
}
fn trie_nodes_recorded_for_key(&self, key: &[u8]) -> RecordedForKey {
self.recorded_keys.get(key).copied().unwrap_or(RecordedForKey::None)
}
}