diff --git a/linera-execution/src/execution_state_actor.rs b/linera-execution/src/execution_state_actor.rs index 1e55ea71e68..e1d8e0f113f 100644 --- a/linera-execution/src/execution_state_actor.rs +++ b/linera-execution/src/execution_state_actor.rs @@ -112,14 +112,7 @@ where } OwnerBalances { callback } => { - let mut balances = Vec::new(); - self.system - .balances - .for_each_index_value(|owner, balance| { - balances.push((owner, balance)); - Ok(()) - }) - .await?; + let balances = self.system.balances.index_values().await?; callback.respond(balances.into_iter().collect()); } diff --git a/linera-execution/src/test_utils/mod.rs b/linera-execution/src/test_utils/mod.rs index 3cc722ebc5a..a9df4f1e9fe 100644 --- a/linera-execution/src/test_utils/mod.rs +++ b/linera-execution/src/test_utils/mod.rs @@ -173,17 +173,7 @@ where } async fn registered_application_count(&self) -> anyhow::Result { - let mut count = 0; - - self.registry - .known_applications - .for_each_index(|_| { - count += 1; - Ok(()) - }) - .await?; - - Ok(count) + Ok(self.registry.known_applications.count().await?) } async fn register_mock_application_with( diff --git a/linera-execution/tests/contract_runtime_apis.rs b/linera-execution/tests/contract_runtime_apis.rs index e427a7c5bd7..a29312da6cf 100644 --- a/linera-execution/tests/contract_runtime_apis.rs +++ b/linera-execution/tests/contract_runtime_apis.rs @@ -800,15 +800,7 @@ impl TransferTestEndpoint { Some(account_owner) => (Amount::ZERO, vec![(account_owner, amount)]), }; - let mut balances = Vec::new(); - - system - .balances - .for_each_index_value(|owner, balance| { - balances.push((owner, balance)); - Ok(()) - }) - .await?; + let balances = system.balances.index_values().await?; assert_eq!(*system.balance.get(), expected_chain_balance); assert_eq!(balances, expected_balances); diff --git a/linera-views/src/views/collection_view.rs b/linera-views/src/views/collection_view.rs index 128e6b55ad3..fbe7f747e5c 100644 --- a/linera-views/src/views/collection_view.rs +++ b/linera-views/src/views/collection_view.rs @@ -586,6 +586,31 @@ where .await?; Ok(keys) } + + /// Returns the number of entries in the collection. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::{create_test_memory_context, MemoryContext}; + /// # use linera_views::collection_view::ByteCollectionView; + /// # use linera_views::register_view::RegisterView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut view: ByteCollectionView<_, RegisterView<_, String>> = + /// ByteCollectionView::load(context).await.unwrap(); + /// view.load_entry_mut(&[0, 1]).await.unwrap(); + /// view.load_entry_mut(&[0, 2]).await.unwrap(); + /// assert_eq!(view.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + let mut count = 0; + self.for_each_key(|_key| { + count += 1; + Ok(()) + }) + .await?; + Ok(count) + } } #[async_trait] @@ -907,13 +932,32 @@ where /// ``` pub async fn indices(&self) -> Result, ViewError> { let mut indices = Vec::new(); - self.for_each_index(|index: I| { + self.for_each_index(|index| { indices.push(index); Ok(()) }) .await?; Ok(indices) } + + /// Returns the number of entries in the collection. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::{create_test_memory_context, MemoryContext}; + /// # use linera_views::collection_view::CollectionView; + /// # use linera_views::register_view::RegisterView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut view: CollectionView<_, u64, RegisterView<_, String>> = + /// CollectionView::load(context).await.unwrap(); + /// view.load_entry_mut(&23).await.unwrap(); + /// view.load_entry_mut(&25).await.unwrap(); + /// assert_eq!(view.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.collection.count().await + } } impl CollectionView @@ -1267,13 +1311,32 @@ where /// ``` pub async fn indices(&self) -> Result, ViewError> { let mut indices = Vec::new(); - self.for_each_index(|index: I| { + self.for_each_index(|index| { indices.push(index); Ok(()) }) .await?; Ok(indices) } + + /// Returns the number of entries in the collection. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::{create_test_memory_context, MemoryContext}; + /// # use linera_views::collection_view::CollectionView; + /// # use linera_views::register_view::RegisterView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut view: CollectionView<_, u64, RegisterView<_, String>> = + /// CollectionView::load(context).await.unwrap(); + /// view.load_entry_mut(&23).await.unwrap(); + /// view.load_entry_mut(&25).await.unwrap(); + /// assert_eq!(view.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.collection.count().await + } } impl CustomCollectionView diff --git a/linera-views/src/views/map_view.rs b/linera-views/src/views/map_view.rs index 713a3f619b9..dc441656bed 100644 --- a/linera-views/src/views/map_view.rs +++ b/linera-views/src/views/map_view.rs @@ -365,7 +365,7 @@ impl ByteMapView where C: Context, ViewError: From, - V: Sync + Serialize + DeserializeOwned + 'static, + V: Serialize + 'static, { /// Applies the function f on each index (aka key) which has the assigned prefix. /// Keys are visited in the lexicographic order. The shortened key is send to the @@ -709,7 +709,7 @@ impl ByteMapView where C: Context, ViewError: From, - V: Sync + Send + Serialize + DeserializeOwned + 'static, + V: Send + Serialize + DeserializeOwned + 'static, { /// Returns the list of keys and values of the map matching a prefix /// in lexicographic order. @@ -824,7 +824,7 @@ impl HashableView for ByteMapView where C: Context + Send + Sync, ViewError: From, - V: Clone + Send + Sync + Serialize + DeserializeOwned + 'static, + V: Send + Sync + Serialize + 'static, { type Hasher = sha3::Sha3_256; @@ -866,7 +866,7 @@ impl View for MapView where C: Context + Send + Sync, ViewError: From, - I: Send + Sync + Serialize, + I: Sync, V: Send + Sync + Serialize, { const NUM_INIT_KEYS: usize = ByteMapView::::NUM_INIT_KEYS; @@ -912,7 +912,7 @@ impl ClonableView for MapView where C: Context + Send + Sync, ViewError: From, - I: Send + Sync + Serialize, + I: Sync, V: Clone + Send + Sync + Serialize, { fn clone_unchecked(&mut self) -> Result { @@ -1068,7 +1068,7 @@ impl MapView where C: Context + Sync, ViewError: From, - I: Sync + Send + Serialize + DeserializeOwned, + I: Send + DeserializeOwned, V: Sync + Serialize + DeserializeOwned + 'static, { /// Returns the list of indices in the map. The order is determined by serialization. @@ -1250,6 +1250,64 @@ where } } +impl MapView +where + C: Context + Sync, + ViewError: From, + I: Send + DeserializeOwned, + V: Sync + Send + Serialize + DeserializeOwned + 'static, +{ + /// Obtains all the `(index,value)` pairs. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::create_test_memory_context; + /// # use linera_views::map_view::MapView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut map: MapView<_, String, _> = MapView::load(context).await.unwrap(); + /// map.insert("Italian", String::from("Ciao")); + /// let index_values = map.index_values().await.unwrap(); + /// assert_eq!( + /// index_values, + /// vec![("Italian".to_string(), "Ciao".to_string())] + /// ); + /// # }) + /// ``` + pub async fn index_values(&self) -> Result, ViewError> { + let prefix = Vec::new(); + let mut key_values = Vec::new(); + self.map + .for_each_key_value( + |key, bytes| { + let index = C::deserialize_value(key)?; + let value = C::deserialize_value(bytes)?; + key_values.push((index, value)); + Ok(()) + }, + prefix, + ) + .await?; + Ok(key_values) + } + + /// Obtains the number of entries in the map + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::create_test_memory_context; + /// # use linera_views::map_view::MapView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut map: MapView<_, String, _> = MapView::load(context).await.unwrap(); + /// map.insert("Italian", String::from("Ciao")); + /// map.insert("French", String::from("Bonjour")); + /// assert_eq!(map.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.map.count().await + } +} + impl MapView where C: Context + Sync, @@ -1512,8 +1570,8 @@ impl CustomMapView where C: Context + Sync, ViewError: From, - I: Sync + Send + CustomSerialize, - V: Sync + Serialize + DeserializeOwned + 'static, + I: Send + CustomSerialize, + V: Serialize + DeserializeOwned + 'static, { /// Returns the list of indices in the map. The order is determined /// by the custom serialization. @@ -1698,6 +1756,64 @@ where } } +impl CustomMapView +where + C: Context + Sync, + ViewError: From, + I: Send + CustomSerialize, + V: Sync + Send + Serialize + DeserializeOwned + 'static, +{ + /// Obtains all the `(index,value)` pairs. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::create_test_memory_context; + /// # use linera_views::map_view::MapView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut map: MapView<_, String, _> = MapView::load(context).await.unwrap(); + /// map.insert("Italian", String::from("Ciao")); + /// let index_values = map.index_values().await.unwrap(); + /// assert_eq!( + /// index_values, + /// vec![("Italian".to_string(), "Ciao".to_string())] + /// ); + /// # }) + /// ``` + pub async fn index_values(&self) -> Result, ViewError> { + let prefix = Vec::new(); + let mut key_values = Vec::new(); + self.map + .for_each_key_value( + |key, bytes| { + let index = I::from_custom_bytes(key)?; + let value = C::deserialize_value(bytes)?; + key_values.push((index, value)); + Ok(()) + }, + prefix, + ) + .await?; + Ok(key_values) + } + + /// Obtains the number of entries in the map + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::create_test_memory_context; + /// # use linera_views::map_view::MapView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut map: MapView<_, String, _> = MapView::load(context).await.unwrap(); + /// map.insert("Italian", String::from("Ciao")); + /// map.insert("French", String::from("Bonjour")); + /// assert_eq!(map.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.map.count().await + } +} + impl CustomMapView where C: Context + Sync, @@ -1723,7 +1839,7 @@ where pub async fn get_mut_or_default(&mut self, index: &Q) -> Result<&mut V, ViewError> where I: Borrow, - Q: Sync + Send + Serialize + CustomSerialize, + Q: Send + CustomSerialize, { let short_key = index.to_custom_bytes()?; self.map.get_mut_or_default(&short_key).await diff --git a/linera-views/src/views/reentrant_collection_view.rs b/linera-views/src/views/reentrant_collection_view.rs index fac2524b103..d5378e73b39 100644 --- a/linera-views/src/views/reentrant_collection_view.rs +++ b/linera-views/src/views/reentrant_collection_view.rs @@ -842,6 +842,31 @@ where Ok(keys) } + /// Returns the number of indices of the collection. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::{create_test_memory_context, MemoryContext}; + /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView; + /// # use linera_views::register_view::RegisterView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> = + /// ReentrantByteCollectionView::load(context).await.unwrap(); + /// view.try_load_entry_mut(&[0, 1]).await.unwrap(); + /// view.try_load_entry_mut(&[0, 2]).await.unwrap(); + /// assert_eq!(view.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + let mut count = 0; + self.for_each_key(|_key| { + count += 1; + Ok(()) + }) + .await?; + Ok(count) + } + /// Applies a function f on each index (aka key). Keys are visited in a /// lexicographic order. If the function returns false then the loop /// ends prematurely. @@ -1426,7 +1451,7 @@ where /// ``` pub async fn indices(&self) -> Result, ViewError> { let mut indices = Vec::new(); - self.for_each_index(|index: I| { + self.for_each_index(|index| { indices.push(index); Ok(()) }) @@ -1434,6 +1459,25 @@ where Ok(indices) } + /// Returns the number of indices in the collection. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::{create_test_memory_context, MemoryContext}; + /// # use linera_views::reentrant_collection_view::ReentrantCollectionView; + /// # use linera_views::register_view::RegisterView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> = + /// ReentrantCollectionView::load(context).await.unwrap(); + /// view.try_load_entry_mut(&23).await.unwrap(); + /// view.try_load_entry_mut(&25).await.unwrap(); + /// assert_eq!(view.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.collection.count().await + } + /// Applies a function f on each index. Indices are visited in an order /// determined by the serialization. If the function f returns false then /// the loop ends prematurely. @@ -1925,7 +1969,7 @@ where /// ``` pub async fn indices(&self) -> Result, ViewError> { let mut indices = Vec::new(); - self.for_each_index(|index: I| { + self.for_each_index(|index| { indices.push(index); Ok(()) }) @@ -1933,6 +1977,25 @@ where Ok(indices) } + /// Returns the number of entries in the collection. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::{create_test_memory_context, MemoryContext}; + /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView; + /// # use linera_views::register_view::RegisterView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> = + /// ReentrantCustomCollectionView::load(context).await.unwrap(); + /// view.try_load_entry_mut(&23).await.unwrap(); + /// view.try_load_entry_mut(&25).await.unwrap(); + /// assert_eq!(view.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.collection.count().await + } + /// Applies a function f on each index. Indices are visited in an order /// determined by the custom serialization. If the function f returns false /// then the loop ends prematurely. diff --git a/linera-views/src/views/set_view.rs b/linera-views/src/views/set_view.rs index 2a53d63598f..ca3854db359 100644 --- a/linera-views/src/views/set_view.rs +++ b/linera-views/src/views/set_view.rs @@ -232,6 +232,28 @@ where Ok(keys) } + /// Returns the number of entries in the set. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::{context::create_test_memory_context, set_view::ByteSetView}; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut set = ByteSetView::load(context).await.unwrap(); + /// set.insert(vec![0, 1]); + /// set.insert(vec![0, 2]); + /// assert_eq!(set.keys().await.unwrap(), vec![vec![0, 1], vec![0, 2]]); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + let mut count = 0; + self.for_each_key(|_key| { + count += 1; + Ok(()) + }) + .await?; + Ok(count) + } + /// Applies a function f on each index (aka key). Keys are visited in a /// lexicographic order. If the function returns false, then the loop ends /// prematurely. @@ -527,8 +549,8 @@ where /// # }) /// ``` pub async fn indices(&self) -> Result, ViewError> { - let mut indices = Vec::::new(); - self.for_each_index(|index: I| { + let mut indices = Vec::new(); + self.for_each_index(|index| { indices.push(index); Ok(()) }) @@ -536,6 +558,21 @@ where Ok(indices) } + /// Returns the number of entries in the set. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::{context::create_test_memory_context, set_view::SetView}; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap(); + /// set.insert(&(34 as u32)); + /// assert_eq!(set.count().await.unwrap(), 1); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.set.count().await + } + /// Applies a function f on each index. Indices are visited in an order /// determined by the serialization. If the function returns false, then the /// loop ends prematurely. @@ -800,8 +837,8 @@ where /// # }) /// ``` pub async fn indices(&self) -> Result, ViewError> { - let mut indices = Vec::::new(); - self.for_each_index(|index: I| { + let mut indices = Vec::new(); + self.for_each_index(|index| { indices.push(index); Ok(()) }) @@ -809,6 +846,23 @@ where Ok(indices) } + /// Returns the number of entries of the set. + /// ```rust + /// # tokio_test::block_on(async { + /// # use linera_views::context::create_test_memory_context; + /// # use linera_views::set_view::CustomSetView; + /// # use linera_views::views::View; + /// # let context = create_test_memory_context(); + /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap(); + /// set.insert(&(34 as u128)); + /// set.insert(&(37 as u128)); + /// assert_eq!(set.count().await.unwrap(), 2); + /// # }) + /// ``` + pub async fn count(&self) -> Result { + self.set.count().await + } + /// Applies a function f on each index. Indices are visited in an order /// determined by the custom serialization. If the function does return /// false, then the loop prematurely ends.