pub struct SetMapper<SA, T, A = CurrentStorage>where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,{ /* private fields */ }Expand description
A storage mapper implementing an ordered set with efficient membership testing and iteration.
§Storage Layout
The SetMapper uses a QueueMapper for ordering and separate storage for value-to-node mapping:
-
Ordered elements (via
QueueMapper):base_key + ".info"→QueueMapperInfo(length, front, back, new node counter)base_key + ".node_links" + node_id→Nodestructure (previous, next)base_key + ".value" + node_id→ the stored value
-
Value lookup (for fast membership testing):
base_key + ".node_id" + encoded_value→ node ID (0 means not present)
This dual structure enables both O(1) membership testing and ordered iteration.
§Main Operations
- Insert:
insert(value)- Adds a value if not already present. O(1) with storage writes. - Remove:
remove(value)- Removes a value from the set. O(1) with storage writes. - Contains:
contains(value)- Checks membership. O(1) with one storage read. - Iteration:
iter()- Iterates in insertion order;iter_from(value)- starts from specific value. - Navigation:
next(value)/previous(value)- Gets adjacent elements in insertion order. - Batch:
remove_all(iter)- Removes multiple values efficiently.
§Insertion Order
Unlike typical sets, SetMapper maintains insertion order - elements are stored in the order
they were added. This makes it a hybrid between a set and a sequence.
§Trade-offs
- Pros: O(1) insert, remove, and contains; maintains insertion order; efficient iteration.
- Cons: Higher storage overhead than
UnorderedSetMapper(uses QueueMapper internally); no random access; removed elements leave gaps in node ID space.
§Comparison with UnorderedSetMapper
- SetMapper: Maintains insertion order, uses queue-based structure, slightly higher storage cost
- UnorderedSetMapper: No ordering guarantees, uses vec-based structure, more compact storage
§Use Cases
- Whitelists/blacklists where insertion order matters
- Unique collections requiring ordered iteration
- Sets where you need to navigate between elements
- Scenarios requiring both fast lookup and sequential processing
§Example
// Insert values
assert!(mapper.insert(100));
assert!(mapper.insert(200));
assert!(mapper.insert(300));
assert!(!mapper.insert(200)); // Already exists, returns false
assert_eq!(mapper.len(), 3);
assert!(mapper.contains(&200));
// Navigate between elements
let next = mapper.next(&200);
assert_eq!(next, Some(300));
let prev = mapper.previous(&200);
assert_eq!(prev, Some(100));
// Remove element
assert!(mapper.remove(&200));
assert!(!mapper.contains(&200));
assert_eq!(mapper.len(), 2);
// Iterate in insertion order
for value in mapper.iter() {
// Process in order: 100, 300
}
// Batch removal
mapper.remove_all(vec![100, 300]);
assert!(mapper.is_empty());Implementations§
Source§impl<SA, T> SetMapper<SA, T, CurrentStorage>
impl<SA, T> SetMapper<SA, T, CurrentStorage>
Sourcepub fn insert(&mut self, value: T) -> bool
pub fn insert(&mut self, value: T) -> bool
Adds a value to the set.
If the set did not have this value present, true is returned.
If the set did have this value present, false is returned.
Sourcepub fn remove(&mut self, value: &T) -> bool
pub fn remove(&mut self, value: &T) -> bool
Removes a value from the set. Returns whether the value was present in the set.
pub fn remove_all<I>(&mut self, iter: I)where
I: IntoIterator<Item = T>,
Source§impl<SA, A, T> SetMapper<SA, T, A>where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + NestedEncode + NestedDecode,
impl<SA, A, T> SetMapper<SA, T, A>where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + NestedEncode + NestedDecode,
pub fn build_named_value_key(&self, name: &[u8], value: &T) -> StorageKey<SA>
Sourcepub fn iter(&self) -> Iter<'_, SA, A, T>
pub fn iter(&self) -> Iter<'_, SA, A, T>
An iterator visiting all elements in arbitrary order.
The iterator element type is &'a T.
pub fn iter_from(&self, value: &T) -> Iter<'_, SA, A, T>
Sourcepub fn check_internal_consistency(&self) -> bool
pub fn check_internal_consistency(&self) -> bool
Checks the internal consistency of the collection. Used for unit tests.
pub fn next(&self, value: &T) -> Option<T>
pub fn previous(&self, value: &T) -> Option<T>
pub fn front(&self) -> Option<T>
pub fn back(&self) -> Option<T>
Trait Implementations§
Source§impl<SA, T> Extend<T> for SetMapper<SA, T, CurrentStorage>
impl<SA, T> Extend<T> for SetMapper<SA, T, CurrentStorage>
Source§fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = T>,
fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = T>,
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)Source§impl<'a, SA, A, T> IntoIterator for &'a SetMapper<SA, T, A>where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
impl<'a, SA, A, T> IntoIterator for &'a SetMapper<SA, T, A>where
SA: StorageMapperApi,
A: StorageAddress<SA>,
T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
Source§impl<SA, T> StorageClearable for SetMapper<SA, T, CurrentStorage>
impl<SA, T> StorageClearable for SetMapper<SA, T, CurrentStorage>
Source§impl<SA, T> StorageMapper<SA> for SetMapper<SA, T, CurrentStorage>
impl<SA, T> StorageMapper<SA> for SetMapper<SA, T, CurrentStorage>
Source§fn new(base_key: StorageKey<SA>) -> Self
fn new(base_key: StorageKey<SA>) -> Self
#[storage_mapper] annotation generated code.Source§impl<SA, T> StorageMapperFromAddress<SA> for SetMapper<SA, T, ManagedAddress<SA>>
impl<SA, T> StorageMapperFromAddress<SA> for SetMapper<SA, T, ManagedAddress<SA>>
Source§fn new_from_address(
address: ManagedAddress<SA>,
base_key: StorageKey<SA>,
) -> Self
fn new_from_address( address: ManagedAddress<SA>, base_key: StorageKey<SA>, ) -> Self
#[storage_mapper_from_address]
annotation generated code.Source§impl<SA, T> TopEncodeMulti for SetMapper<SA, T, CurrentStorage>
Behaves like a MultiResultVec when an endpoint result.
impl<SA, T> TopEncodeMulti for SetMapper<SA, T, CurrentStorage>
Behaves like a MultiResultVec when an endpoint result.
Source§fn multi_encode_or_handle_err<O, H>(
&self,
output: &mut O,
h: H,
) -> Result<(), H::HandledErr>where
O: TopEncodeMultiOutput,
H: EncodeErrorHandler,
fn multi_encode_or_handle_err<O, H>(
&self,
output: &mut O,
h: H,
) -> Result<(), H::HandledErr>where
O: TopEncodeMultiOutput,
H: EncodeErrorHandler,
top_encode that can handle errors as soon as they occur.
For instance in can exit immediately and make sure that if it returns, it is a success.
By not deferring error handling, this can lead to somewhat smaller bytecode.Source§fn multi_encode<O>(&self, output: &mut O) -> Result<(), EncodeError>where
O: TopEncodeMultiOutput,
fn multi_encode<O>(&self, output: &mut O) -> Result<(), EncodeError>where
O: TopEncodeMultiOutput,
Source§impl<SA, T> TypeAbi for SetMapper<SA, T, CurrentStorage>
Behaves like a MultiResultVec when an endpoint result.
impl<SA, T> TypeAbi for SetMapper<SA, T, CurrentStorage>
Behaves like a MultiResultVec when an endpoint result.