diff --git a/memorydb/Cargo.toml b/memorydb/Cargo.toml
index 20c4365..81b5874 100644
--- a/memorydb/Cargo.toml
+++ b/memorydb/Cargo.toml
@@ -7,7 +7,6 @@ repository = "https://github.com/paritytech/parity-common"
license = "GPL-3.0"
[dependencies]
-elastic-array = "0.10"
heapsize = "0.4"
hashdb = { version = "0.2", path = "../hashdb" }
plain_hasher = { version = "0.2", path = "../plain_hasher", default-features = false }
diff --git a/memorydb/src/lib.rs b/memorydb/src/lib.rs
index f07bce8..9e4c5dc 100644
--- a/memorydb/src/lib.rs
+++ b/memorydb/src/lib.rs
@@ -15,7 +15,6 @@
// along with Parity. If not, see .
//! Reference-counted memory-based `HashDB` implementation.
-extern crate elastic_array;
extern crate hashdb;
extern crate heapsize;
extern crate rlp;
@@ -23,7 +22,7 @@ extern crate rlp;
#[cfg(test)] extern crate tiny_keccak;
#[cfg(test)] extern crate ethereum_types;
-use hashdb::{HashDB, Hasher as KeyHasher, DBValue, AsHashDB};
+use hashdb::{HashDB, Hasher as KeyHasher, AsHashDB};
use heapsize::HeapSizeOf;
use rlp::NULL_RLP;
use std::collections::hash_map::Entry;
@@ -82,23 +81,64 @@ type FastMap = HashMap<::Out, T, hash::BuildHasherDefault<
/// }
/// ```
#[derive(Clone, PartialEq)]
-pub struct MemoryDB {
- data: FastMap,
+pub struct MemoryDB {
+ data: FastMap,
hashed_null_node: H::Out,
+ null_node_data: T,
}
-impl Default for MemoryDB where H: KeyHasher, H::Out: HeapSizeOf {
+impl<'a, H, T> Default for MemoryDB where H: KeyHasher, H::Out: HeapSizeOf, T: From<&'a [u8]> {
fn default() -> Self { Self::new() }
}
-impl MemoryDB where H: KeyHasher, H::Out: HeapSizeOf {
+impl<'a, H, T> MemoryDB
+ where H: KeyHasher,
+ H::Out: HeapSizeOf,
+ T: From<&'a [u8]>,
+{
/// Create a new instance of the memory DB.
- pub fn new() -> MemoryDB {
- MemoryDB {
- data: FastMap::::default(),
- hashed_null_node: H::hash(&NULL_RLP)
+ pub fn new() -> Self {
+ MemoryDB::from_null_node(&NULL_RLP, NULL_RLP.as_ref().into())
+ }
+}
+
+impl MemoryDB
+ where H: KeyHasher,
+ H::Out: HeapSizeOf,
+ T: Default,
+{
+ /// Remove an element and delete it from storage if reference count reaches zero.
+ /// If the value was purged, return the old value.
+ pub fn remove_and_purge(&mut self, key: &::Out) -> Option {
+ if key == &self.hashed_null_node {
+ return None;
+ }
+ match self.data.entry(key.clone()) {
+ Entry::Occupied(mut entry) =>
+ if entry.get().1 == 1 {
+ Some(entry.remove().0)
+ } else {
+ entry.get_mut().1 -= 1;
+ None
+ },
+ Entry::Vacant(entry) => {
+ entry.insert((T::default(), -1)); // FIXME: shouldn't it be purged?
+ None
+ }
}
}
+}
+
+impl MemoryDB {
+
+ /// Create a new `MemoryDB` from a given null key/data
+ pub fn from_null_node(null_key: &[u8], null_node_data: T) -> Self {
+ MemoryDB {
+ data: FastMap::::default(),
+ hashed_null_node: H::hash(null_key),
+ null_node_data,
+ }
+ }
/// Clear all data from the database.
///
@@ -131,7 +171,7 @@ impl MemoryDB where H: KeyHasher, H::Out: HeapSizeOf {
}
/// Return the internal map of hashes to data, clearing the current state.
- pub fn drain(&mut self) -> FastMap {
+ pub fn drain(&mut self) -> FastMap {
mem::replace(&mut self.data, FastMap::::default())
}
@@ -140,37 +180,11 @@ impl MemoryDB where H: KeyHasher, H::Out: HeapSizeOf {
///
/// Even when Some is returned, the data is only guaranteed to be useful
/// when the refs > 0.
- pub fn raw(&self, key: &::Out) -> Option<(DBValue, i32)> {
+ pub fn raw(&self, key: &::Out) -> Option<(&T, i32)> {
if key == &self.hashed_null_node {
- return Some((DBValue::from_slice(&NULL_RLP), 1));
- }
- self.data.get(key).cloned()
- }
-
- /// Returns the size of allocated heap memory
- pub fn mem_used(&self) -> usize {
- self.data.heap_size_of_children()
- }
-
- /// Remove an element and delete it from storage if reference count reaches zero.
- /// If the value was purged, return the old value.
- pub fn remove_and_purge(&mut self, key: &::Out) -> Option {
- if key == &self.hashed_null_node {
- return None;
- }
- match self.data.entry(key.clone()) {
- Entry::Occupied(mut entry) =>
- if entry.get().1 == 1 {
- Some(entry.remove().0)
- } else {
- entry.get_mut().1 -= 1;
- None
- },
- Entry::Vacant(entry) => {
- entry.insert((DBValue::new(), -1));
- None
- }
+ return Some((&self.null_node_data, 1));
}
+ self.data.get(key).map(|(value, count)| (value, *count))
}
/// Consolidate all the entries of `other` into `self`.
@@ -192,8 +206,21 @@ impl MemoryDB where H: KeyHasher, H::Out: HeapSizeOf {
}
}
-impl HashDB for MemoryDB {
+impl MemoryDB
+ where H: KeyHasher,
+ H::Out: HeapSizeOf,
+ T: HeapSizeOf,
+{
+ /// Returns the size of allocated heap memory
+ pub fn mem_used(&self) -> usize {
+ self.data.heap_size_of_children()
+ }
+}
+impl HashDB for MemoryDB
+ where H: KeyHasher,
+ T: Default + PartialEq + for<'a> From<&'a [u8]> + Send + Sync,
+{
fn keys(&self) -> HashMap {
self.data.iter()
.filter_map(|(k, v)| if v.1 != 0 {
@@ -204,13 +231,13 @@ impl HashDB for MemoryDB {
.collect()
}
- fn get(&self, key: &H::Out) -> Option {
+ fn get(&self, key: &H::Out) -> Option<&T> {
if key == &self.hashed_null_node {
- return Some(DBValue::from_slice(&NULL_RLP));
+ return Some(&self.null_node_data);
}
match self.data.get(key) {
- Some(&(ref d, rc)) if rc > 0 => Some(d.clone()),
+ Some(&(ref d, rc)) if rc > 0 => Some(d),
_ => None
}
}
@@ -226,28 +253,8 @@ impl HashDB for MemoryDB {
}
}
- fn insert(&mut self, value: &[u8]) -> H::Out {
- if value == &NULL_RLP {
- return self.hashed_null_node.clone();
- }
- let key = H::hash(value);
- match self.data.entry(key) {
- Entry::Occupied(mut entry) => {
- let &mut (ref mut old_value, ref mut rc) = entry.get_mut();
- if *rc <= 0 {
- *old_value = DBValue::from_slice(value);
- }
- *rc += 1;
- },
- Entry::Vacant(entry) => {
- entry.insert((DBValue::from_slice(value), 1));
- },
- }
- key
- }
-
- fn emplace(&mut self, key:H::Out, value: DBValue) {
- if &*value == &NULL_RLP {
+ fn emplace(&mut self, key:H::Out, value: T) {
+ if value == self.null_node_data {
return;
}
@@ -265,6 +272,26 @@ impl HashDB for MemoryDB {
}
}
+ fn insert(&mut self, value: &[u8]) -> H::Out {
+ if value == &NULL_RLP {
+ return self.hashed_null_node.clone();
+ }
+ let key = H::hash(value);
+ match self.data.entry(key) {
+ Entry::Occupied(mut entry) => {
+ let &mut (ref mut old_value, ref mut rc) = entry.get_mut();
+ if *rc <= 0 {
+ *old_value = value.into();
+ }
+ *rc += 1;
+ },
+ Entry::Vacant(entry) => {
+ entry.insert((value.into(), 1));
+ },
+ }
+ key
+ }
+
fn remove(&mut self, key: &H::Out) {
if key == &self.hashed_null_node {
return;
@@ -276,15 +303,19 @@ impl HashDB for MemoryDB {
*rc -= 1;
},
Entry::Vacant(entry) => {
- entry.insert((DBValue::new(), -1));
+ entry.insert((T::default(), -1));
},
}
}
+
}
-impl AsHashDB for MemoryDB {
- fn as_hashdb(&self) -> &HashDB { self }
- fn as_hashdb_mut(&mut self) -> &mut HashDB { self }
+impl AsHashDB for MemoryDB
+ where H: KeyHasher,
+ T: Default + PartialEq + for<'a> From<&'a[u8]> + Send + Sync,
+{
+ fn as_hashdb(&self) -> &HashDB { self }
+ fn as_hashdb_mut(&mut self) -> &mut HashDB { self }
}
#[cfg(test)]