Always return a typed structure from lmdb store (#3312)

We have a method get which returns a Vec, it's used in cases when we can't implement FromLmdbBytes or Readable on a desired type, eg when both traits and type are external for the current crate. This approach requires an extra allocation of a Vec, this PR introduces a method which accepts desirialzer as closure, which allows to desrialize in place without an intermidiate heap allocation.

It's still possible to get a Vec if needed, just pass a Vec constructor to get_with.
This commit is contained in:
hashmap 2020-05-05 11:00:23 +02:00 committed by GitHub
parent c82199bb97
commit 2397407dc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 11 deletions

View file

@ -348,11 +348,11 @@ impl<'a> Batch<'a> {
} }
fn get_legacy_input_bitmap(&self, bh: &Hash) -> Result<Bitmap, Error> { fn get_legacy_input_bitmap(&self, bh: &Hash) -> Result<Bitmap, Error> {
if let Ok(Some(bytes)) = self.db.get(&to_key(BLOCK_INPUT_BITMAP_PREFIX, bh)) { option_to_not_found(
Ok(Bitmap::deserialize(&bytes)) self.db
} else { .get_with(&to_key(BLOCK_INPUT_BITMAP_PREFIX, bh), Bitmap::deserialize),
Err(Error::NotFoundErr("legacy block input bitmap".to_string())) || "legacy block input bitmap".to_string(),
} )
} }
/// Get the "spent index" from the db for the specified block. /// Get the "spent index" from the db for the specified block.

View file

@ -235,14 +235,15 @@ impl Store {
} }
/// Gets a value from the db, provided its key /// Gets a value from the db, provided its key
pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Error> { pub fn get_with<T, F>(&self, key: &[u8], f: F) -> Result<Option<T>, Error>
where
F: Fn(&[u8]) -> T,
{
let db = self.db.read(); let db = self.db.read();
let txn = lmdb::ReadTransaction::new(self.env.clone())?; let txn = lmdb::ReadTransaction::new(self.env.clone())?;
let access = txn.access(); let access = txn.access();
let res = access.get(&db.as_ref().unwrap(), key); let res = access.get(&db.as_ref().unwrap(), key);
res.map(|res: &[u8]| res.to_vec()) res.map(f).to_opt().map_err(From::from)
.to_opt()
.map_err(From::from)
} }
/// Gets a `Readable` value from the db, provided its key. Encapsulates /// Gets a `Readable` value from the db, provided its key. Encapsulates
@ -345,8 +346,11 @@ impl<'a> Batch<'a> {
} }
/// gets a value from the db, provided its key /// gets a value from the db, provided its key
pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Error> { pub fn get_with<T, F>(&self, key: &[u8], f: F) -> Result<Option<T>, Error>
self.store.get(key) where
F: Fn(&[u8]) -> T,
{
self.store.get_with(key, f)
} }
/// Whether the provided key exists /// Whether the provided key exists