diff --git a/crates/fuel-core/src/database/transactions.rs b/crates/fuel-core/src/database/transactions.rs index 027439c08c..c7ec700f62 100644 --- a/crates/fuel-core/src/database/transactions.rs +++ b/crates/fuel-core/src/database/transactions.rs @@ -35,7 +35,7 @@ use fuel_core_types::{ services::txpool::TransactionStatus, }; -/// Teh tables allows to iterate over all transactions owned by an address. +/// These tables allow iteration over all transactions owned by an address. pub struct OwnedTransactions; impl Mappable for OwnedTransactions { diff --git a/crates/storage/src/blueprint.rs b/crates/storage/src/blueprint.rs index 53bb1d853a..3db1ee73e8 100644 --- a/crates/storage/src/blueprint.rs +++ b/crates/storage/src/blueprint.rs @@ -110,23 +110,30 @@ where { /// Initializes the storage with a bunch of key-value pairs. /// In some cases, this method may be more performant than [`Self::insert`]. - fn init( - storage: &mut S, - column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()>; + fn init<'a, Iter>(storage: &mut S, column: S::Column, set: Iter) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a; /// Inserts the batch of key-value pairs into the storage. - fn insert( + fn insert<'a, Iter>( storage: &mut S, column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()>; + set: Iter, + ) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a; /// Removes the batch of key-value pairs from the storage. - fn remove( + fn remove<'a, Iter>( storage: &mut S, column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()>; + set: Iter, + ) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a; } diff --git a/crates/storage/src/blueprint/plain.rs b/crates/storage/src/blueprint/plain.rs index 3eeac8bb51..7a9e696e81 100644 --- a/crates/storage/src/blueprint/plain.rs +++ b/crates/storage/src/blueprint/plain.rs @@ -98,19 +98,25 @@ where M: Mappable + TableWithBlueprint>, M::Blueprint: Blueprint, { - fn init( - storage: &mut S, - column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()> { + fn init<'a, Iter>(storage: &mut S, column: S::Column, set: Iter) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a, + { Self::insert(storage, column, set) } - fn insert( + fn insert<'a, Iter>( storage: &mut S, column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()> { + set: Iter, + ) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a, + { storage.batch_write(&mut set.map(|(key, value)| { let key_encoder = >::KeyCodec::encode(key); let key_bytes = key_encoder.as_bytes().to_vec(); @@ -120,11 +126,15 @@ where })) } - fn remove( + fn remove<'a, Iter>( storage: &mut S, column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()> { + set: Iter, + ) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + { storage.batch_write(&mut set.map(|key| { let key_encoder = >::KeyCodec::encode(key); let key_bytes = key_encoder.as_bytes().to_vec(); diff --git a/crates/storage/src/blueprint/sparse.rs b/crates/storage/src/blueprint/sparse.rs index 39768c2047..3607bdd752 100644 --- a/crates/storage/src/blueprint/sparse.rs +++ b/crates/storage/src/blueprint/sparse.rs @@ -292,11 +292,12 @@ where + StorageMutate + StorageMutate, { - fn init( - storage: &mut S, - column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()> { + fn init<'a, Iter>(storage: &mut S, column: S::Column, set: Iter) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a, + { let mut set = set.peekable(); let primary_key; @@ -353,11 +354,16 @@ where Ok(()) } - fn insert( + fn insert<'a, Iter>( storage: &mut S, column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()> { + set: Iter, + ) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a, + { let mut set = set.peekable(); let primary_key; @@ -406,11 +412,15 @@ where Ok(()) } - fn remove( + fn remove<'a, Iter>( storage: &mut S, column: S::Column, - set: &mut dyn Iterator, - ) -> StorageResult<()> { + set: Iter, + ) -> StorageResult<()> + where + Iter: 'a + Iterator, + M::Key: 'a, + { let mut set = set.peekable(); let primary_key; diff --git a/crates/storage/src/codec/manual.rs b/crates/storage/src/codec/manual.rs index 020a389387..34a93566cd 100644 --- a/crates/storage/src/codec/manual.rs +++ b/crates/storage/src/codec/manual.rs @@ -7,8 +7,10 @@ use crate::codec::{ Decode, Encode, }; -use fuel_core_types::fuel_vm::ContractsAssetKey; -use fuel_vm_private::storage::ContractsStateKey; +use fuel_core_types::fuel_vm::{ + ContractsAssetKey, + ContractsStateKey, +}; use std::borrow::Cow; /// The codec allows the definition of manual implementation for specific type `T`. diff --git a/crates/storage/src/codec/postcard.rs b/crates/storage/src/codec/postcard.rs index a8218fa884..4b1284afcf 100644 --- a/crates/storage/src/codec/postcard.rs +++ b/crates/storage/src/codec/postcard.rs @@ -13,24 +13,24 @@ use std::borrow::Cow; /// The codec is used to serialized/deserialized types that supports `serde::Serialize` and `serde::Deserialize`. pub struct Postcard; -impl Encode for Postcard +impl Encode for Postcard where - K: ?Sized + serde::Serialize, + T: ?Sized + serde::Serialize, { - type Encoder<'a> = Cow<'a, [u8]> where K: 'a; + type Encoder<'a> = Cow<'a, [u8]> where T: 'a; - fn encode(value: &K) -> Self::Encoder<'_> { + fn encode(value: &T) -> Self::Encoder<'_> { Cow::Owned(postcard::to_allocvec(value).expect( "It should be impossible to fail unless serialization is not implemented, which is not true for our types.", )) } } -impl Decode for Postcard +impl Decode for Postcard where - V: serde::de::DeserializeOwned, + T: serde::de::DeserializeOwned, { - fn decode(bytes: &[u8]) -> anyhow::Result { + fn decode(bytes: &[u8]) -> anyhow::Result { Ok(postcard::from_bytes(bytes)?) } } diff --git a/crates/storage/src/codec/raw.rs b/crates/storage/src/codec/raw.rs index 2a3a9d17b1..fba697c2ae 100644 --- a/crates/storage/src/codec/raw.rs +++ b/crates/storage/src/codec/raw.rs @@ -11,22 +11,22 @@ use std::borrow::Cow; /// The codec is used for types that are already represented by bytes. pub struct Raw; -impl Encode for Raw +impl Encode for Raw where - K: ?Sized + AsRef<[u8]>, + T: ?Sized + AsRef<[u8]>, { - type Encoder<'a> = Cow<'a, [u8]> where K: 'a; + type Encoder<'a> = Cow<'a, [u8]> where T: 'a; - fn encode(t: &K) -> Self::Encoder<'_> { + fn encode(t: &T) -> Self::Encoder<'_> { Cow::Borrowed(t.as_ref()) } } -impl Decode for Raw +impl Decode for Raw where - for<'a> V: TryFrom<&'a [u8]>, + for<'a> T: TryFrom<&'a [u8]>, { - fn decode(bytes: &[u8]) -> anyhow::Result { - V::try_from(bytes).map_err(|_| anyhow::anyhow!("Unable to decode bytes")) + fn decode(bytes: &[u8]) -> anyhow::Result { + T::try_from(bytes).map_err(|_| anyhow::anyhow!("Unable to decode bytes")) } } diff --git a/crates/storage/src/kv_store.rs b/crates/storage/src/kv_store.rs index 2fa8b1602c..5d6154684d 100644 --- a/crates/storage/src/kv_store.rs +++ b/crates/storage/src/kv_store.rs @@ -113,6 +113,7 @@ pub enum WriteOperation { #[impl_tools::autoimpl(for &T, &mut T, Box, Arc)] pub trait BatchOperations: KeyValueStore { /// Writes the batch of the entries into the storage. + // TODO: Replace `dyn Iterator` with a generic iterator when `Database` will not use `dyn BatchOperations`. fn batch_write( &self, entries: &mut dyn Iterator, Self::Column, WriteOperation)>, diff --git a/crates/storage/src/lib.rs b/crates/storage/src/lib.rs index facb188660..9a6d6ba832 100644 --- a/crates/storage/src/lib.rs +++ b/crates/storage/src/lib.rs @@ -125,19 +125,24 @@ pub trait StorageBatchMutate: StorageMutate { /// # Errors /// /// Returns an error if the storage is already initialized. - fn init_storage( - &mut self, - set: &mut dyn Iterator, - ) -> Result<()>; + fn init_storage<'a, Iter>(&mut self, set: Iter) -> Result<()> + where + Iter: 'a + Iterator, + Type::Key: 'a, + Type::Value: 'a; /// Inserts the key-value pair into the storage in batch. - fn insert_batch( - &mut self, - set: &mut dyn Iterator, - ) -> Result<()>; + fn insert_batch<'a, Iter>(&mut self, set: Iter) -> Result<()> + where + Iter: 'a + Iterator, + Type::Key: 'a, + Type::Value: 'a; /// Removes the key-value pairs from the storage in batch. - fn remove_batch(&mut self, set: &mut dyn Iterator) -> Result<()>; + fn remove_batch<'a, Iter>(&mut self, set: Iter) -> Result<()> + where + Iter: 'a + Iterator, + Type::Key: 'a; } /// Creates `StorageError::NotFound` error with file and line information inside. diff --git a/crates/storage/src/structured_storage.rs b/crates/storage/src/structured_storage.rs index 63647b0310..04076644ce 100644 --- a/crates/storage/src/structured_storage.rs +++ b/crates/storage/src/structured_storage.rs @@ -131,24 +131,29 @@ where M: Mappable + TableWithBlueprint, M::Blueprint: SupportsBatching, { - fn init_storage( - &mut self, - set: &mut dyn Iterator, - ) -> Result<(), Self::Error> { + fn init_storage<'a, Iter>(&mut self, set: Iter) -> Result<(), Self::Error> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a, + { ::Blueprint::init(&mut self.storage, M::column(), set) } - fn insert_batch( - &mut self, - set: &mut dyn Iterator, - ) -> Result<(), Self::Error> { + fn insert_batch<'a, Iter>(&mut self, set: Iter) -> Result<(), Self::Error> + where + Iter: 'a + Iterator, + M::Key: 'a, + M::Value: 'a, + { ::Blueprint::insert(&mut self.storage, M::column(), set) } - fn remove_batch( - &mut self, - set: &mut dyn Iterator, - ) -> Result<(), Self::Error> { + fn remove_batch<'a, Iter>(&mut self, set: Iter) -> Result<(), Self::Error> + where + Iter: 'a + Iterator, + M::Key: 'a, + { ::Blueprint::remove(&mut self.storage, M::column(), set) } } @@ -308,17 +313,50 @@ pub mod test { let mut structured_storage = StructuredStorage::new(&mut storage); let key = $key; + // Given + assert!(!structured_storage + .storage_as_mut::<$table>() + .contains_key(&key) + .unwrap()); + + // When structured_storage .storage_as_mut::<$table>() .insert(&key, &$value_insert) .unwrap(); + // Then assert!(structured_storage .storage_as_mut::<$table>() .contains_key(&key) .unwrap()); } + #[test] + fn exists_false_after_removing() { + let mut storage = InMemoryStorage::default(); + let mut structured_storage = StructuredStorage::new(&mut storage); + let key = $key; + + // Given + structured_storage + .storage_as_mut::<$table>() + .insert(&key, &$value_insert) + .unwrap(); + + // When + structured_storage + .storage_as_mut::<$table>() + .remove(&key) + .unwrap(); + + // Then + assert!(!structured_storage + .storage_as_mut::<$table>() + .contains_key(&key) + .unwrap()); + } + #[test] fn batch_mutate_works() { use $crate::rand::{