referrerpolicy=no-referrer-when-downgrade

frame_support/storage/types/
counted_map.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Storage counted map type.
19
20use crate::{
21	storage::{
22		generator::StorageMap as _,
23		types::{
24			OptionQuery, QueryKindTrait, StorageEntryMetadataBuilder, StorageMap, StorageValue,
25			ValueQuery,
26		},
27		StorageAppend, StorageDecodeLength, StorageTryAppend,
28	},
29	traits::{Get, GetDefault, StorageInfo, StorageInfoTrait, StorageInstance},
30	Never,
31};
32use alloc::{vec, vec::Vec};
33use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen, Ref};
34use sp_io::MultiRemovalResults;
35use sp_metadata_ir::StorageEntryMetadataIR;
36use sp_runtime::traits::Saturating;
37
38/// A wrapper around a [`StorageMap`] and a [`StorageValue`] (with the value being `u32`) to keep
39/// track of how many items are in a map, without needing to iterate all the values.
40///
41/// This storage item has additional storage read and write overhead when manipulating values
42/// compared to a regular storage map.
43///
44/// For functions where we only add or remove a value, a single storage read is needed to check if
45/// that value already exists. For mutate functions, two storage reads are used to check if the
46/// value existed before and after the mutation.
47///
48/// Whenever the counter needs to be updated, an additional read and write occurs to update that
49/// counter.
50///
51/// The total number of items currently stored in the map can be retrieved with the
52/// [`CountedStorageMap::count`] method.
53///
54/// For general information regarding the `#[pallet::storage]` attribute, refer to
55/// [`crate::pallet_macros::storage`].
56///
57/// # Examples
58///
59/// Declaring a counted map:
60///
61/// ```
62/// #[frame_support::pallet]
63/// mod pallet {
64/// # 	use frame_support::pallet_prelude::*;
65/// # 	#[pallet::config]
66/// # 	pub trait Config: frame_system::Config {}
67/// # 	#[pallet::pallet]
68/// # 	pub struct Pallet<T>(_);
69/// 	/// A kitchen-sink CountedStorageMap, with all possible additional attributes.
70///     #[pallet::storage]
71/// 	#[pallet::getter(fn foo)]
72/// 	#[pallet::storage_prefix = "OtherFoo"]
73/// 	#[pallet::unbounded]
74///     pub type Foo<T> = CountedStorageMap<
75/// 		_,
76/// 		Blake2_128Concat,
77/// 		u32,
78/// 		u32,
79/// 		ValueQuery,
80/// 	>;
81///
82/// 	/// Alternative named syntax.
83/// 	#[pallet::storage]
84///     pub type Bar<T> = CountedStorageMap<
85/// 		Hasher = Blake2_128Concat,
86/// 		Key = u32,
87/// 		Value = u32,
88/// 		QueryKind = ValueQuery
89/// 	>;
90/// }
91/// ```
92///
93/// Using a counted map in action:
94#[doc = docify::embed!("src/storage/types/counted_map.rs", test_simple_count_works)]
95pub struct CountedStorageMap<
96	Prefix,
97	Hasher,
98	Key,
99	Value,
100	QueryKind = OptionQuery,
101	OnEmpty = GetDefault,
102	MaxValues = GetDefault,
103>(core::marker::PhantomData<(Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues)>);
104
105/// The requirement for an instance of [`CountedStorageMap`].
106pub trait CountedStorageMapInstance: StorageInstance {
107	/// The prefix to use for the counter storage value.
108	type CounterPrefix: StorageInstance;
109}
110
111// Private helper trait to access map from counted storage map.
112trait MapWrapper {
113	type Map;
114}
115
116impl<P: CountedStorageMapInstance, H, K, V, Q, O, M> MapWrapper
117	for CountedStorageMap<P, H, K, V, Q, O, M>
118{
119	type Map = StorageMap<P, H, K, V, Q, O, M>;
120}
121
122/// The numeric counter type.
123pub type Counter = u32;
124
125type CounterFor<P> =
126	StorageValue<<P as CountedStorageMapInstance>::CounterPrefix, Counter, ValueQuery>;
127
128/// On removal logic for updating counter while draining upon some prefix with
129/// [`crate::storage::PrefixIterator`].
130pub struct OnRemovalCounterUpdate<Prefix>(core::marker::PhantomData<Prefix>);
131
132impl<Prefix: CountedStorageMapInstance> crate::storage::PrefixIteratorOnRemoval
133	for OnRemovalCounterUpdate<Prefix>
134{
135	fn on_removal(_key: &[u8], _value: &[u8]) {
136		CounterFor::<Prefix>::mutate(|value| value.saturating_dec());
137	}
138}
139
140impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
141	CountedStorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
142where
143	Prefix: CountedStorageMapInstance,
144	Hasher: crate::hash::StorageHasher,
145	Key: FullCodec,
146	Value: FullCodec,
147	QueryKind: QueryKindTrait<Value, OnEmpty>,
148	OnEmpty: Get<QueryKind::Query> + 'static,
149	MaxValues: Get<Option<u32>>,
150{
151	/// The key used to store the counter of the map.
152	pub fn counter_storage_final_key() -> [u8; 32] {
153		CounterFor::<Prefix>::hashed_key()
154	}
155
156	/// The prefix used to generate the key of the map.
157	pub fn map_storage_final_prefix() -> Vec<u8> {
158		use crate::storage::generator::StorageMap;
159		<Self as MapWrapper>::Map::prefix_hash().to_vec()
160	}
161
162	/// Get the storage key used to fetch a value corresponding to a specific key.
163	pub fn hashed_key_for<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Vec<u8> {
164		<Self as MapWrapper>::Map::hashed_key_for(key)
165	}
166
167	/// Does the value (explicitly) exist in storage?
168	pub fn contains_key<KeyArg: EncodeLike<Key>>(key: KeyArg) -> bool {
169		<Self as MapWrapper>::Map::contains_key(key)
170	}
171
172	/// Load the value associated with the given key from the map.
173	pub fn get<KeyArg: EncodeLike<Key>>(key: KeyArg) -> QueryKind::Query {
174		<Self as MapWrapper>::Map::get(key)
175	}
176
177	/// Try to get the value for the given key from the map.
178	///
179	/// Returns `Ok` if it exists, `Err` if not.
180	pub fn try_get<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Result<Value, ()> {
181		<Self as MapWrapper>::Map::try_get(key)
182	}
183
184	/// Store or remove the value to be associated with `key` so that `get` returns the `query`.
185	pub fn set<KeyArg: EncodeLike<Key>>(key: KeyArg, q: QueryKind::Query) {
186		match QueryKind::from_query_to_optional_value(q) {
187			Some(v) => Self::insert(key, v),
188			None => Self::remove(key),
189		}
190	}
191
192	/// Swap the values of two keys.
193	pub fn swap<KeyArg1: EncodeLike<Key>, KeyArg2: EncodeLike<Key>>(key1: KeyArg1, key2: KeyArg2) {
194		<Self as MapWrapper>::Map::swap(key1, key2)
195	}
196
197	/// Store a value to be associated with the given key from the map.
198	pub fn insert<KeyArg: EncodeLike<Key>, ValArg: EncodeLike<Value>>(key: KeyArg, val: ValArg) {
199		if !<Self as MapWrapper>::Map::contains_key(Ref::from(&key)) {
200			CounterFor::<Prefix>::mutate(|value| value.saturating_inc());
201		}
202		<Self as MapWrapper>::Map::insert(key, val)
203	}
204
205	/// Remove the value under a key.
206	pub fn remove<KeyArg: EncodeLike<Key>>(key: KeyArg) {
207		if <Self as MapWrapper>::Map::contains_key(Ref::from(&key)) {
208			CounterFor::<Prefix>::mutate(|value| value.saturating_dec());
209		}
210		<Self as MapWrapper>::Map::remove(key)
211	}
212
213	/// Mutate the value under a key.
214	pub fn mutate<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut QueryKind::Query) -> R>(
215		key: KeyArg,
216		f: F,
217	) -> R {
218		Self::try_mutate(key, |v| Ok::<R, Never>(f(v)))
219			.expect("`Never` can not be constructed; qed")
220	}
221
222	/// Mutate the item, only if an `Ok` value is returned.
223	pub fn try_mutate<KeyArg, R, E, F>(key: KeyArg, f: F) -> Result<R, E>
224	where
225		KeyArg: EncodeLike<Key>,
226		F: FnOnce(&mut QueryKind::Query) -> Result<R, E>,
227	{
228		Self::try_mutate_exists(key, |option_value_ref| {
229			let option_value = core::mem::replace(option_value_ref, None);
230			let mut query = <Self as MapWrapper>::Map::from_optional_value_to_query(option_value);
231			let res = f(&mut query);
232			let option_value = <Self as MapWrapper>::Map::from_query_to_optional_value(query);
233			let _ = core::mem::replace(option_value_ref, option_value);
234			res
235		})
236	}
237
238	/// Mutate the value under a key. Deletes the item if mutated to a `None`.
239	pub fn mutate_exists<KeyArg: EncodeLike<Key>, R, F: FnOnce(&mut Option<Value>) -> R>(
240		key: KeyArg,
241		f: F,
242	) -> R {
243		Self::try_mutate_exists(key, |v| Ok::<R, Never>(f(v)))
244			.expect("`Never` can not be constructed; qed")
245	}
246
247	/// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`.
248	/// `f` will always be called with an option representing if the storage item exists (`Some<V>`)
249	/// or if the storage item does not exist (`None`), independent of the `QueryType`.
250	pub fn try_mutate_exists<KeyArg, R, E, F>(key: KeyArg, f: F) -> Result<R, E>
251	where
252		KeyArg: EncodeLike<Key>,
253		F: FnOnce(&mut Option<Value>) -> Result<R, E>,
254	{
255		<Self as MapWrapper>::Map::try_mutate_exists(key, |option_value| {
256			let existed = option_value.is_some();
257			let res = f(option_value);
258			let exist = option_value.is_some();
259
260			if res.is_ok() {
261				if existed && !exist {
262					// Value was deleted
263					CounterFor::<Prefix>::mutate(|value| value.saturating_dec());
264				} else if !existed && exist {
265					// Value was added
266					CounterFor::<Prefix>::mutate(|value| value.saturating_inc());
267				}
268			}
269			res
270		})
271	}
272
273	/// Take the value under a key.
274	pub fn take<KeyArg: EncodeLike<Key>>(key: KeyArg) -> QueryKind::Query {
275		let removed_value = <Self as MapWrapper>::Map::mutate_exists(key, |value| value.take());
276		if removed_value.is_some() {
277			CounterFor::<Prefix>::mutate(|value| value.saturating_dec());
278		}
279		<Self as MapWrapper>::Map::from_optional_value_to_query(removed_value)
280	}
281
282	/// Append the given items to the value in the storage.
283	///
284	/// `Value` is required to implement `codec::EncodeAppend`.
285	///
286	/// # Warning
287	///
288	/// If the storage item is not encoded properly, the storage will be overwritten and set to
289	/// `[item]`. Any default value set for the storage item will be ignored on overwrite.
290	pub fn append<Item, EncodeLikeItem, EncodeLikeKey>(key: EncodeLikeKey, item: EncodeLikeItem)
291	where
292		EncodeLikeKey: EncodeLike<Key>,
293		Item: Encode,
294		EncodeLikeItem: EncodeLike<Item>,
295		Value: StorageAppend<Item>,
296	{
297		if !<Self as MapWrapper>::Map::contains_key(Ref::from(&key)) {
298			CounterFor::<Prefix>::mutate(|value| value.saturating_inc());
299		}
300		<Self as MapWrapper>::Map::append(key, item)
301	}
302
303	/// Read the length of the storage value without decoding the entire value under the given
304	/// `key`.
305	///
306	/// `Value` is required to implement [`StorageDecodeLength`].
307	///
308	/// If the value does not exists or it fails to decode the length, `None` is returned. Otherwise
309	/// `Some(len)` is returned.
310	///
311	/// # Warning
312	///
313	/// `None` does not mean that `get()` does not return a value. The default value is completely
314	/// ignored by this function.
315	pub fn decode_len<KeyArg: EncodeLike<Key>>(key: KeyArg) -> Option<usize>
316	where
317		Value: StorageDecodeLength,
318	{
319		<Self as MapWrapper>::Map::decode_len(key)
320	}
321
322	/// Migrate an item with the given `key` from a defunct `OldHasher` to the current hasher.
323	///
324	/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
325	pub fn migrate_key<OldHasher: crate::hash::StorageHasher, KeyArg: EncodeLike<Key>>(
326		key: KeyArg,
327	) -> Option<Value> {
328		<Self as MapWrapper>::Map::migrate_key::<OldHasher, _>(key)
329	}
330
331	/// Remove all values in the map.
332	#[deprecated = "Use `clear` instead"]
333	pub fn remove_all() {
334		#[allow(deprecated)]
335		<Self as MapWrapper>::Map::remove_all(None);
336		CounterFor::<Prefix>::kill();
337	}
338
339	/// Attempt to remove all items from the map.
340	///
341	/// Returns [`MultiRemovalResults`](sp_io::MultiRemovalResults) to inform about the result. Once
342	/// the resultant `maybe_cursor` field is `None`, then no further items remain to be deleted.
343	///
344	/// NOTE: After the initial call for any given map, it is important that no further items
345	/// are inserted into the map. If so, then the map may not be empty when the resultant
346	/// `maybe_cursor` is `None`.
347	///
348	/// # Limit
349	///
350	/// A `limit` must always be provided through in order to cap the maximum
351	/// amount of deletions done in a single call. This is one fewer than the
352	/// maximum number of backend iterations which may be done by this operation and as such
353	/// represents the maximum number of backend deletions which may happen. A `limit` of zero
354	/// implies that no keys will be deleted, though there may be a single iteration done.
355	///
356	/// # Cursor
357	///
358	/// A *cursor* may be passed in to this operation with `maybe_cursor`. `None` should only be
359	/// passed once (in the initial call) for any given storage map. Subsequent calls
360	/// operating on the same map should always pass `Some`, and this should be equal to the
361	/// previous call result's `maybe_cursor` field.
362	pub fn clear(limit: u32, maybe_cursor: Option<&[u8]>) -> MultiRemovalResults {
363		let result = <Self as MapWrapper>::Map::clear(limit, maybe_cursor);
364		match result.maybe_cursor {
365			None => CounterFor::<Prefix>::kill(),
366			Some(_) => CounterFor::<Prefix>::mutate(|x| x.saturating_reduce(result.unique)),
367		}
368		result
369	}
370
371	/// Iter over all value of the storage.
372	///
373	/// NOTE: If a value failed to decode because storage is corrupted then it is skipped.
374	pub fn iter_values() -> crate::storage::PrefixIterator<Value, OnRemovalCounterUpdate<Prefix>> {
375		<Self as MapWrapper>::Map::iter_values().convert_on_removal()
376	}
377
378	/// Translate the values of all elements by a function `f`, in the map in no particular order.
379	///
380	/// By returning `None` from `f` for an element, you'll remove it from the map.
381	///
382	/// NOTE: If a value fail to decode because storage is corrupted then it is skipped.
383	///
384	/// # Warning
385	///
386	/// This function must be used with care, before being updated the storage still contains the
387	/// old type, thus other calls (such as `get`) will fail at decoding it.
388	///
389	/// # Usage
390	///
391	/// This would typically be called inside the module implementation of on_runtime_upgrade.
392	pub fn translate_values<OldValue: Decode, F: FnMut(OldValue) -> Option<Value>>(mut f: F) {
393		<Self as MapWrapper>::Map::translate_values(|old_value| {
394			let res = f(old_value);
395			if res.is_none() {
396				CounterFor::<Prefix>::mutate(|value| value.saturating_dec());
397			}
398			res
399		})
400	}
401
402	/// Try and append the given item to the value in the storage.
403	///
404	/// Is only available if `Value` of the storage implements [`StorageTryAppend`].
405	pub fn try_append<KArg, Item, EncodeLikeItem>(key: KArg, item: EncodeLikeItem) -> Result<(), ()>
406	where
407		KArg: EncodeLike<Key>,
408		Item: Encode,
409		EncodeLikeItem: EncodeLike<Item>,
410		Value: StorageTryAppend<Item>,
411	{
412		let bound = Value::bound();
413		let current = <Self as MapWrapper>::Map::decode_len(Ref::from(&key)).unwrap_or_default();
414		if current < bound {
415			CounterFor::<Prefix>::mutate(|value| value.saturating_inc());
416			let key = <Self as MapWrapper>::Map::hashed_key_for(key);
417			sp_io::storage::append(&key, item.encode());
418			Ok(())
419		} else {
420			Err(())
421		}
422	}
423
424	/// Initialize the counter with the actual number of items in the map.
425	///
426	/// This function iterates through all the items in the map and sets the counter. This operation
427	/// can be very heavy, so use with caution.
428	///
429	/// Returns the number of items in the map which is used to set the counter.
430	pub fn initialize_counter() -> Counter {
431		let count = Self::iter_values().count() as Counter;
432		CounterFor::<Prefix>::set(count);
433		count
434	}
435
436	/// Return the count.
437	pub fn count() -> Counter {
438		CounterFor::<Prefix>::get()
439	}
440}
441
442impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
443	CountedStorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
444where
445	Prefix: CountedStorageMapInstance,
446	Hasher: crate::hash::StorageHasher + crate::ReversibleStorageHasher,
447	Key: FullCodec,
448	Value: FullCodec,
449	QueryKind: QueryKindTrait<Value, OnEmpty>,
450	OnEmpty: Get<QueryKind::Query> + 'static,
451	MaxValues: Get<Option<u32>>,
452{
453	/// Enumerate all elements in the map in no particular order.
454	///
455	/// If you alter the map while doing this, you'll get undefined results.
456	pub fn iter() -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate<Prefix>> {
457		<Self as MapWrapper>::Map::iter().convert_on_removal()
458	}
459
460	/// Remove all elements from the map and iterate through them in no particular order.
461	///
462	/// If you add elements to the map while doing this, you'll get undefined results.
463	pub fn drain() -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate<Prefix>> {
464		<Self as MapWrapper>::Map::drain().convert_on_removal()
465	}
466
467	/// Translate the values of all elements by a function `f`, in the map in no particular order.
468	///
469	/// By returning `None` from `f` for an element, you'll remove it from the map.
470	///
471	/// NOTE: If a value fail to decode because storage is corrupted then it is skipped.
472	pub fn translate<O: Decode, F: FnMut(Key, O) -> Option<Value>>(mut f: F) {
473		<Self as MapWrapper>::Map::translate(|key, old_value| {
474			let res = f(key, old_value);
475			if res.is_none() {
476				CounterFor::<Prefix>::mutate(|value| value.saturating_dec());
477			}
478			res
479		})
480	}
481
482	/// Enumerate all elements in the counted map after a specified `starting_raw_key` in no
483	/// particular order.
484	///
485	/// If you alter the map while doing this, you'll get undefined results.
486	pub fn iter_from(
487		starting_raw_key: Vec<u8>,
488	) -> crate::storage::PrefixIterator<(Key, Value), OnRemovalCounterUpdate<Prefix>> {
489		<Self as MapWrapper>::Map::iter_from(starting_raw_key).convert_on_removal()
490	}
491
492	/// Enumerate all keys in the counted map.
493	///
494	/// If you alter the map while doing this, you'll get undefined results.
495	pub fn iter_keys() -> crate::storage::KeyPrefixIterator<Key> {
496		<Self as MapWrapper>::Map::iter_keys()
497	}
498}
499
500impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> StorageEntryMetadataBuilder
501	for CountedStorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
502where
503	Prefix: CountedStorageMapInstance,
504	Hasher: crate::hash::StorageHasher,
505	Key: FullCodec + scale_info::StaticTypeInfo,
506	Value: FullCodec + scale_info::StaticTypeInfo,
507	QueryKind: QueryKindTrait<Value, OnEmpty>,
508	OnEmpty: Get<QueryKind::Query> + 'static,
509	MaxValues: Get<Option<u32>>,
510{
511	fn build_metadata(
512		deprecation_status: sp_metadata_ir::ItemDeprecationInfoIR,
513		docs: Vec<&'static str>,
514		entries: &mut Vec<StorageEntryMetadataIR>,
515	) {
516		<Self as MapWrapper>::Map::build_metadata(deprecation_status.clone(), docs, entries);
517		CounterFor::<Prefix>::build_metadata(
518			deprecation_status,
519			if cfg!(feature = "no-metadata-docs") {
520				vec![]
521			} else {
522				vec!["Counter for the related counted storage map"]
523			},
524			entries,
525		);
526	}
527}
528
529impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues> crate::traits::StorageInfoTrait
530	for CountedStorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
531where
532	Prefix: CountedStorageMapInstance,
533	Hasher: crate::hash::StorageHasher,
534	Key: FullCodec + MaxEncodedLen,
535	Value: FullCodec + MaxEncodedLen,
536	QueryKind: QueryKindTrait<Value, OnEmpty>,
537	OnEmpty: Get<QueryKind::Query> + 'static,
538	MaxValues: Get<Option<u32>>,
539{
540	fn storage_info() -> Vec<StorageInfo> {
541		[<Self as MapWrapper>::Map::storage_info(), CounterFor::<Prefix>::storage_info()].concat()
542	}
543}
544
545/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
546impl<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
547	crate::traits::PartialStorageInfoTrait
548	for CountedStorageMap<Prefix, Hasher, Key, Value, QueryKind, OnEmpty, MaxValues>
549where
550	Prefix: CountedStorageMapInstance,
551	Hasher: crate::hash::StorageHasher,
552	Key: FullCodec,
553	Value: FullCodec,
554	QueryKind: QueryKindTrait<Value, OnEmpty>,
555	OnEmpty: Get<QueryKind::Query> + 'static,
556	MaxValues: Get<Option<u32>>,
557{
558	fn partial_storage_info() -> Vec<StorageInfo> {
559		[<Self as MapWrapper>::Map::partial_storage_info(), CounterFor::<Prefix>::storage_info()]
560			.concat()
561	}
562}
563
564#[cfg(test)]
565mod test {
566	use super::*;
567	use crate::{
568		hash::*,
569		storage::{bounded_vec::BoundedVec, types::ValueQuery},
570		traits::ConstU32,
571	};
572	use sp_io::{hashing::twox_128, TestExternalities};
573	use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR};
574
575	struct Prefix;
576	impl StorageInstance for Prefix {
577		fn pallet_prefix() -> &'static str {
578			"test"
579		}
580		const STORAGE_PREFIX: &'static str = "foo";
581	}
582
583	struct CounterPrefix;
584	impl StorageInstance for CounterPrefix {
585		fn pallet_prefix() -> &'static str {
586			"test"
587		}
588		const STORAGE_PREFIX: &'static str = "counter_for_foo";
589	}
590	impl CountedStorageMapInstance for Prefix {
591		type CounterPrefix = CounterPrefix;
592	}
593
594	struct ADefault;
595	impl crate::traits::Get<u32> for ADefault {
596		fn get() -> u32 {
597			97
598		}
599	}
600	#[crate::storage_alias]
601	type ExampleCountedMap = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
602
603	#[test]
604	fn storage_alias_works() {
605		TestExternalities::default().execute_with(|| {
606			assert_eq!(ExampleCountedMap::count(), 0);
607			ExampleCountedMap::insert(3, 10);
608		})
609	}
610
611	#[test]
612	fn test_value_query() {
613		type A = CountedStorageMap<Prefix, Twox64Concat, u16, u32, ValueQuery, ADefault>;
614
615		TestExternalities::default().execute_with(|| {
616			let mut k: Vec<u8> = vec![];
617			k.extend(&twox_128(b"test"));
618			k.extend(&twox_128(b"foo"));
619			k.extend(&3u16.twox_64_concat());
620			assert_eq!(A::hashed_key_for(3).to_vec(), k);
621
622			assert_eq!(A::contains_key(3), false);
623			assert_eq!(A::get(3), ADefault::get());
624			assert_eq!(A::try_get(3), Err(()));
625			assert_eq!(A::count(), 0);
626
627			// Insert non-existing.
628			A::insert(3, 10);
629
630			assert_eq!(A::contains_key(3), true);
631			assert_eq!(A::get(3), 10);
632			assert_eq!(A::try_get(3), Ok(10));
633			assert_eq!(A::count(), 1);
634
635			// Swap non-existing with existing.
636			A::swap(4, 3);
637
638			assert_eq!(A::contains_key(3), false);
639			assert_eq!(A::get(3), ADefault::get());
640			assert_eq!(A::try_get(3), Err(()));
641			assert_eq!(A::contains_key(4), true);
642			assert_eq!(A::get(4), 10);
643			assert_eq!(A::try_get(4), Ok(10));
644			assert_eq!(A::count(), 1);
645
646			// Swap existing with non-existing.
647			A::swap(4, 3);
648
649			assert_eq!(A::try_get(3), Ok(10));
650			assert_eq!(A::contains_key(4), false);
651			assert_eq!(A::get(4), ADefault::get());
652			assert_eq!(A::try_get(4), Err(()));
653			assert_eq!(A::count(), 1);
654
655			A::insert(4, 11);
656
657			assert_eq!(A::try_get(3), Ok(10));
658			assert_eq!(A::try_get(4), Ok(11));
659			assert_eq!(A::count(), 2);
660
661			// Swap 2 existing.
662			A::swap(3, 4);
663
664			assert_eq!(A::try_get(3), Ok(11));
665			assert_eq!(A::try_get(4), Ok(10));
666			assert_eq!(A::count(), 2);
667
668			// Insert an existing key, shouldn't increment counted values.
669			A::insert(3, 12);
670
671			assert_eq!(A::try_get(3), Ok(12));
672			assert_eq!(A::count(), 2);
673
674			// Remove non-existing.
675			A::remove(2);
676
677			assert_eq!(A::contains_key(2), false);
678			assert_eq!(A::count(), 2);
679
680			// Remove existing.
681			A::remove(3);
682
683			assert_eq!(A::try_get(3), Err(()));
684			assert_eq!(A::count(), 1);
685
686			// Mutate non-existing to existing.
687			A::mutate(3, |query| {
688				assert_eq!(*query, ADefault::get());
689				*query = 40;
690			});
691
692			assert_eq!(A::try_get(3), Ok(40));
693			assert_eq!(A::count(), 2);
694
695			// Mutate existing to existing.
696			A::mutate(3, |query| {
697				assert_eq!(*query, 40);
698				*query = 40;
699			});
700
701			assert_eq!(A::try_get(3), Ok(40));
702			assert_eq!(A::count(), 2);
703
704			// Try fail mutate non-existing to existing.
705			A::try_mutate(2, |query| {
706				assert_eq!(*query, ADefault::get());
707				*query = 4;
708				Result::<(), ()>::Err(())
709			})
710			.err()
711			.unwrap();
712
713			assert_eq!(A::try_get(2), Err(()));
714			assert_eq!(A::count(), 2);
715
716			// Try succeed mutate non-existing to existing.
717			A::try_mutate(2, |query| {
718				assert_eq!(*query, ADefault::get());
719				*query = 41;
720				Result::<(), ()>::Ok(())
721			})
722			.unwrap();
723
724			assert_eq!(A::try_get(2), Ok(41));
725			assert_eq!(A::count(), 3);
726
727			// Try succeed mutate existing to existing.
728			A::try_mutate(2, |query| {
729				assert_eq!(*query, 41);
730				*query = 41;
731				Result::<(), ()>::Ok(())
732			})
733			.unwrap();
734
735			assert_eq!(A::try_get(2), Ok(41));
736			assert_eq!(A::count(), 3);
737
738			// Try fail mutate non-existing to existing.
739			A::try_mutate_exists(1, |query| {
740				assert_eq!(*query, None);
741				*query = Some(4);
742				Result::<(), ()>::Err(())
743			})
744			.err()
745			.unwrap();
746
747			assert_eq!(A::try_get(1), Err(()));
748			assert_eq!(A::count(), 3);
749
750			// Try succeed mutate non-existing to existing.
751			A::try_mutate_exists(1, |query| {
752				assert_eq!(*query, None);
753				*query = Some(43);
754				Result::<(), ()>::Ok(())
755			})
756			.unwrap();
757
758			assert_eq!(A::try_get(1), Ok(43));
759			assert_eq!(A::count(), 4);
760
761			// Try succeed mutate existing to existing.
762			A::try_mutate_exists(1, |query| {
763				assert_eq!(*query, Some(43));
764				*query = Some(45);
765				Result::<(), ()>::Ok(())
766			})
767			.unwrap();
768
769			assert_eq!(A::try_get(1), Ok(45));
770			assert_eq!(A::count(), 4);
771
772			// Try succeed mutate existing to non-existing.
773			A::try_mutate_exists(1, |query| {
774				assert_eq!(*query, Some(45));
775				*query = None;
776				Result::<(), ()>::Ok(())
777			})
778			.unwrap();
779
780			assert_eq!(A::try_get(1), Err(()));
781			assert_eq!(A::count(), 3);
782
783			// Take existing.
784			assert_eq!(A::take(4), 10);
785
786			assert_eq!(A::try_get(4), Err(()));
787			assert_eq!(A::count(), 2);
788
789			// Take non-existing.
790			assert_eq!(A::take(4), ADefault::get());
791
792			assert_eq!(A::try_get(4), Err(()));
793			assert_eq!(A::count(), 2);
794
795			// Remove all.
796			let _ = A::clear(u32::max_value(), None);
797
798			assert_eq!(A::count(), 0);
799			assert_eq!(A::initialize_counter(), 0);
800
801			A::insert(1, 1);
802			A::insert(2, 2);
803
804			// Iter values.
805			assert_eq!(A::iter_values().collect::<Vec<_>>(), vec![2, 1]);
806
807			// Iter drain values.
808			assert_eq!(A::iter_values().drain().collect::<Vec<_>>(), vec![2, 1]);
809			assert_eq!(A::count(), 0);
810
811			A::insert(1, 1);
812			A::insert(2, 2);
813
814			// Test initialize_counter.
815			assert_eq!(A::initialize_counter(), 2);
816
817			// Set non-existing.
818			A::set(30, 100);
819
820			assert_eq!(A::contains_key(30), true);
821			assert_eq!(A::get(30), 100);
822			assert_eq!(A::try_get(30), Ok(100));
823			assert_eq!(A::count(), 3);
824
825			// Set existing.
826			A::set(30, 101);
827
828			assert_eq!(A::contains_key(30), true);
829			assert_eq!(A::get(30), 101);
830			assert_eq!(A::try_get(30), Ok(101));
831			assert_eq!(A::count(), 3);
832		})
833	}
834
835	#[test]
836	fn test_option_query() {
837		type B = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
838
839		TestExternalities::default().execute_with(|| {
840			let mut k: Vec<u8> = vec![];
841			k.extend(&twox_128(b"test"));
842			k.extend(&twox_128(b"foo"));
843			k.extend(&3u16.twox_64_concat());
844			assert_eq!(B::hashed_key_for(3).to_vec(), k);
845
846			assert_eq!(B::contains_key(3), false);
847			assert_eq!(B::get(3), None);
848			assert_eq!(B::try_get(3), Err(()));
849			assert_eq!(B::count(), 0);
850
851			// Insert non-existing.
852			B::insert(3, 10);
853
854			assert_eq!(B::contains_key(3), true);
855			assert_eq!(B::get(3), Some(10));
856			assert_eq!(B::try_get(3), Ok(10));
857			assert_eq!(B::count(), 1);
858
859			// Swap non-existing with existing.
860			B::swap(4, 3);
861
862			assert_eq!(B::contains_key(3), false);
863			assert_eq!(B::get(3), None);
864			assert_eq!(B::try_get(3), Err(()));
865			assert_eq!(B::contains_key(4), true);
866			assert_eq!(B::get(4), Some(10));
867			assert_eq!(B::try_get(4), Ok(10));
868			assert_eq!(B::count(), 1);
869
870			// Swap existing with non-existing.
871			B::swap(4, 3);
872
873			assert_eq!(B::try_get(3), Ok(10));
874			assert_eq!(B::contains_key(4), false);
875			assert_eq!(B::get(4), None);
876			assert_eq!(B::try_get(4), Err(()));
877			assert_eq!(B::count(), 1);
878
879			B::insert(4, 11);
880
881			assert_eq!(B::try_get(3), Ok(10));
882			assert_eq!(B::try_get(4), Ok(11));
883			assert_eq!(B::count(), 2);
884
885			// Swap 2 existing.
886			B::swap(3, 4);
887
888			assert_eq!(B::try_get(3), Ok(11));
889			assert_eq!(B::try_get(4), Ok(10));
890			assert_eq!(B::count(), 2);
891
892			// Insert an existing key, shouldn't increment counted values.
893			B::insert(3, 11);
894
895			assert_eq!(B::count(), 2);
896
897			// Remove non-existing.
898			B::remove(2);
899
900			assert_eq!(B::contains_key(2), false);
901			assert_eq!(B::count(), 2);
902
903			// Remove existing.
904			B::remove(3);
905
906			assert_eq!(B::try_get(3), Err(()));
907			assert_eq!(B::count(), 1);
908
909			// Mutate non-existing to existing.
910			B::mutate(3, |query| {
911				assert_eq!(*query, None);
912				*query = Some(40)
913			});
914
915			assert_eq!(B::try_get(3), Ok(40));
916			assert_eq!(B::count(), 2);
917
918			// Mutate existing to existing.
919			B::mutate(3, |query| {
920				assert_eq!(*query, Some(40));
921				*query = Some(40)
922			});
923
924			assert_eq!(B::try_get(3), Ok(40));
925			assert_eq!(B::count(), 2);
926
927			// Mutate existing to non-existing.
928			B::mutate(3, |query| {
929				assert_eq!(*query, Some(40));
930				*query = None
931			});
932
933			assert_eq!(B::try_get(3), Err(()));
934			assert_eq!(B::count(), 1);
935
936			B::insert(3, 40);
937
938			// Try fail mutate non-existing to existing.
939			B::try_mutate(2, |query| {
940				assert_eq!(*query, None);
941				*query = Some(4);
942				Result::<(), ()>::Err(())
943			})
944			.err()
945			.unwrap();
946
947			assert_eq!(B::try_get(2), Err(()));
948			assert_eq!(B::count(), 2);
949
950			// Try succeed mutate non-existing to existing.
951			B::try_mutate(2, |query| {
952				assert_eq!(*query, None);
953				*query = Some(41);
954				Result::<(), ()>::Ok(())
955			})
956			.unwrap();
957
958			assert_eq!(B::try_get(2), Ok(41));
959			assert_eq!(B::count(), 3);
960
961			// Try succeed mutate existing to existing.
962			B::try_mutate(2, |query| {
963				assert_eq!(*query, Some(41));
964				*query = Some(41);
965				Result::<(), ()>::Ok(())
966			})
967			.unwrap();
968
969			assert_eq!(B::try_get(2), Ok(41));
970			assert_eq!(B::count(), 3);
971
972			// Try succeed mutate existing to non-existing.
973			B::try_mutate(2, |query| {
974				assert_eq!(*query, Some(41));
975				*query = None;
976				Result::<(), ()>::Ok(())
977			})
978			.unwrap();
979
980			assert_eq!(B::try_get(2), Err(()));
981			assert_eq!(B::count(), 2);
982
983			B::insert(2, 41);
984
985			// Try fail mutate non-existing to existing.
986			B::try_mutate_exists(1, |query| {
987				assert_eq!(*query, None);
988				*query = Some(4);
989				Result::<(), ()>::Err(())
990			})
991			.err()
992			.unwrap();
993
994			assert_eq!(B::try_get(1), Err(()));
995			assert_eq!(B::count(), 3);
996
997			// Try succeed mutate non-existing to existing.
998			B::try_mutate_exists(1, |query| {
999				assert_eq!(*query, None);
1000				*query = Some(43);
1001				Result::<(), ()>::Ok(())
1002			})
1003			.unwrap();
1004
1005			assert_eq!(B::try_get(1), Ok(43));
1006			assert_eq!(B::count(), 4);
1007
1008			// Try succeed mutate existing to existing.
1009			B::try_mutate_exists(1, |query| {
1010				assert_eq!(*query, Some(43));
1011				*query = Some(43);
1012				Result::<(), ()>::Ok(())
1013			})
1014			.unwrap();
1015
1016			assert_eq!(B::try_get(1), Ok(43));
1017			assert_eq!(B::count(), 4);
1018
1019			// Try succeed mutate existing to non-existing.
1020			B::try_mutate_exists(1, |query| {
1021				assert_eq!(*query, Some(43));
1022				*query = None;
1023				Result::<(), ()>::Ok(())
1024			})
1025			.unwrap();
1026
1027			assert_eq!(B::try_get(1), Err(()));
1028			assert_eq!(B::count(), 3);
1029
1030			// Take existing.
1031			assert_eq!(B::take(4), Some(10));
1032
1033			assert_eq!(B::try_get(4), Err(()));
1034			assert_eq!(B::count(), 2);
1035
1036			// Take non-existing.
1037			assert_eq!(B::take(4), None);
1038
1039			assert_eq!(B::try_get(4), Err(()));
1040			assert_eq!(B::count(), 2);
1041
1042			// Remove all.
1043			let _ = B::clear(u32::max_value(), None);
1044
1045			assert_eq!(B::count(), 0);
1046			assert_eq!(B::initialize_counter(), 0);
1047
1048			B::insert(1, 1);
1049			B::insert(2, 2);
1050
1051			// Iter values.
1052			assert_eq!(B::iter_values().collect::<Vec<_>>(), vec![2, 1]);
1053
1054			// Iter drain values.
1055			assert_eq!(B::iter_values().drain().collect::<Vec<_>>(), vec![2, 1]);
1056			assert_eq!(B::count(), 0);
1057
1058			B::insert(1, 1);
1059			B::insert(2, 2);
1060
1061			// Test initialize_counter.
1062			assert_eq!(B::initialize_counter(), 2);
1063
1064			// Set non-existing.
1065			B::set(30, Some(100));
1066
1067			assert_eq!(B::contains_key(30), true);
1068			assert_eq!(B::get(30), Some(100));
1069			assert_eq!(B::try_get(30), Ok(100));
1070			assert_eq!(B::count(), 3);
1071
1072			// Set existing.
1073			B::set(30, Some(101));
1074
1075			assert_eq!(B::contains_key(30), true);
1076			assert_eq!(B::get(30), Some(101));
1077			assert_eq!(B::try_get(30), Ok(101));
1078			assert_eq!(B::count(), 3);
1079
1080			// Unset existing.
1081			B::set(30, None);
1082
1083			assert_eq!(B::contains_key(30), false);
1084			assert_eq!(B::get(30), None);
1085			assert_eq!(B::try_get(30), Err(()));
1086
1087			assert_eq!(B::count(), 2);
1088
1089			// Unset non-existing.
1090			B::set(31, None);
1091
1092			assert_eq!(B::contains_key(31), false);
1093			assert_eq!(B::get(31), None);
1094			assert_eq!(B::try_get(31), Err(()));
1095
1096			assert_eq!(B::count(), 2);
1097		})
1098	}
1099
1100	#[test]
1101	fn append_decode_len_works() {
1102		type B = CountedStorageMap<Prefix, Twox64Concat, u16, Vec<u32>>;
1103
1104		TestExternalities::default().execute_with(|| {
1105			assert_eq!(B::decode_len(0), None);
1106			B::append(0, 3);
1107			assert_eq!(B::decode_len(0), Some(1));
1108			B::append(0, 3);
1109			assert_eq!(B::decode_len(0), Some(2));
1110			B::append(0, 3);
1111			assert_eq!(B::decode_len(0), Some(3));
1112		})
1113	}
1114
1115	#[test]
1116	fn try_append_decode_len_works() {
1117		type B = CountedStorageMap<Prefix, Twox64Concat, u16, BoundedVec<u32, ConstU32<3u32>>>;
1118
1119		TestExternalities::default().execute_with(|| {
1120			assert_eq!(B::decode_len(0), None);
1121			B::try_append(0, 3).unwrap();
1122			assert_eq!(B::decode_len(0), Some(1));
1123			B::try_append(0, 3).unwrap();
1124			assert_eq!(B::decode_len(0), Some(2));
1125			B::try_append(0, 3).unwrap();
1126			assert_eq!(B::decode_len(0), Some(3));
1127			B::try_append(0, 3).err().unwrap();
1128			assert_eq!(B::decode_len(0), Some(3));
1129		})
1130	}
1131
1132	#[test]
1133	fn migrate_keys_works() {
1134		type A = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
1135		type B = CountedStorageMap<Prefix, Blake2_128Concat, u16, u32>;
1136		TestExternalities::default().execute_with(|| {
1137			A::insert(1, 1);
1138			assert_eq!(B::migrate_key::<Twox64Concat, _>(1), Some(1));
1139			assert_eq!(B::get(1), Some(1));
1140		})
1141	}
1142
1143	#[test]
1144	fn translate_values() {
1145		type A = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
1146		TestExternalities::default().execute_with(|| {
1147			A::insert(1, 1);
1148			A::insert(2, 2);
1149			A::translate_values::<u32, _>(|old_value| if old_value == 1 { None } else { Some(1) });
1150			assert_eq!(A::count(), 1);
1151			assert_eq!(A::get(2), Some(1));
1152		})
1153	}
1154
1155	#[test]
1156	fn test_iter_drain_translate() {
1157		type A = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
1158		TestExternalities::default().execute_with(|| {
1159			A::insert(1, 1);
1160			A::insert(2, 2);
1161
1162			assert_eq!(A::iter().collect::<Vec<_>>(), vec![(2, 2), (1, 1)]);
1163
1164			assert_eq!(A::count(), 2);
1165
1166			A::translate::<u32, _>(
1167				|key, value| if key == 1 { None } else { Some(key as u32 * value) },
1168			);
1169
1170			assert_eq!(A::count(), 1);
1171
1172			assert_eq!(A::drain().collect::<Vec<_>>(), vec![(2, 4)]);
1173
1174			assert_eq!(A::count(), 0);
1175		})
1176	}
1177
1178	#[test]
1179	fn test_iter_from() {
1180		type A = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
1181		TestExternalities::default().execute_with(|| {
1182			A::insert(1, 1);
1183			A::insert(2, 2);
1184			A::insert(3, 3);
1185			A::insert(4, 4);
1186
1187			// no prefix is same as normal iter.
1188			assert_eq!(A::iter_from(vec![]).collect::<Vec<_>>(), A::iter().collect::<Vec<_>>());
1189
1190			let iter_all = A::iter().collect::<Vec<_>>();
1191			let (before, after) = iter_all.split_at(2);
1192			let last_key = before.last().map(|(k, _)| k).unwrap();
1193			assert_eq!(A::iter_from(A::hashed_key_for(last_key)).collect::<Vec<_>>(), after);
1194		})
1195	}
1196
1197	#[test]
1198	fn test_metadata() {
1199		type A = CountedStorageMap<Prefix, Twox64Concat, u16, u32, ValueQuery, ADefault>;
1200		let mut entries = vec![];
1201		A::build_metadata(
1202			sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated,
1203			vec![],
1204			&mut entries,
1205		);
1206		assert_eq!(
1207			entries,
1208			vec![
1209				StorageEntryMetadataIR {
1210					name: "foo",
1211					modifier: StorageEntryModifierIR::Default,
1212					ty: StorageEntryTypeIR::Map {
1213						hashers: vec![StorageHasherIR::Twox64Concat],
1214						key: scale_info::meta_type::<u16>(),
1215						value: scale_info::meta_type::<u32>(),
1216					},
1217					default: 97u32.encode(),
1218					docs: vec![],
1219					deprecation_info: sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated,
1220				},
1221				StorageEntryMetadataIR {
1222					name: "counter_for_foo",
1223					modifier: StorageEntryModifierIR::Default,
1224					ty: StorageEntryTypeIR::Plain(scale_info::meta_type::<Counter>()),
1225					default: vec![0, 0, 0, 0],
1226					docs: if cfg!(feature = "no-metadata-docs") {
1227						vec![]
1228					} else {
1229						vec!["Counter for the related counted storage map"]
1230					},
1231					deprecation_info: sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated,
1232				},
1233			]
1234		);
1235	}
1236
1237	#[docify::export]
1238	#[test]
1239	fn test_simple_count_works() {
1240		type FooCountedMap = CountedStorageMap<Prefix, Twox64Concat, u16, u32>;
1241		TestExternalities::default().execute_with(|| {
1242			FooCountedMap::insert(1, 1);
1243			FooCountedMap::insert(2, 2);
1244			assert_eq!(FooCountedMap::count(), 2);
1245		});
1246	}
1247}