pub struct SingleValueMapper<SA, T, A = CurrentStorage>{ /* private fields */ }Expand description
A storage mapper for managing a single serializable value with atomic read/write operations.
§Storage Layout
The SingleValueMapper stores a single value directly at its storage key:
base_key→ encoded value of typeT
This is the simplest storage mapper - just one key storing one value.
§Main Operations
- Write:
set(value)- Stores a value (accepts owned or borrowed). O(1). - Read:
get()- Retrieves the stored value. O(1). - Conditional write:
set_if_empty(value)- Stores only if empty. O(1). - Update:
update(|v| {...})- Read-modify-write in one operation. O(1). - Replace:
replace(new_value)- Swaps value and returns old one. O(1). - Take:
take()- Retrieves value and clears storage. O(1). - Clear:
clear()- Removes value from storage. O(1). - Check:
is_empty()- Returns true if no value stored. O(1).
§Value Semantics
- Empty storage: Returns the default/zero value when calling
get() - Setting a value: Overwrites any existing value
- Clearing: Removes the value entirely from storage
- Zero values: A value set to its zero/default may be indistinguishable from empty storage
§Trade-offs
- Pros: Simplest storage pattern; minimal overhead; direct key-value mapping; very efficient.
- Cons: Only one value per mapper; no built-in indexing or collections.
§Use Cases
- Configuration values (flags, thresholds, addresses)
- Global counters or accumulators
- Contract state variables (owner, paused status, etc.)
- Cached computed values
- Simple on-chain variables that don’t need collection semantics
§Example
// Set a value
mapper.set(&owner);
// Check if empty
assert!(!mapper.is_empty());
// Get the value
let current_owner = mapper.get();
assert_eq!(current_owner, owner);
// Conditional set (only if empty)
mapper.set_if_empty(&owner); // Does nothing, already set
// Update in place
mapper.update(|addr| {
// Modify the value
*addr = owner.clone();
});
// Replace and get old value
let old_owner = mapper.replace(&new_owner);
assert_eq!(old_owner, owner);
// Take value (get and clear)
let taken = mapper.take();
assert!(mapper.is_empty());
// Clear storage
mapper.set(&owner);
mapper.clear();
assert!(mapper.is_empty());§Numeric Counter Example
// Initialize counter
counter.set(0u64);
// Increment using update
counter.update(|value| *value += 1);
assert_eq!(counter.get(), 1);
// Increment and return new value
let new_value = counter.update(|value| {
*value += 1;
*value
});
assert_eq!(new_value, 2);Implementations§
Source§impl<SA, T, A> SingleValueMapper<SA, T, A>
impl<SA, T, A> SingleValueMapper<SA, T, A>
Source§impl<SA, T> SingleValueMapper<SA, T, CurrentStorage>
impl<SA, T> SingleValueMapper<SA, T, CurrentStorage>
Sourcepub fn set<BT>(&self, new_value: BT)where
BT: Borrow<T>,
pub fn set<BT>(&self, new_value: BT)where
BT: Borrow<T>,
Saves argument to storage.
Accepts owned item of type T, or any borrowed form of it, such as &T.
Sourcepub fn set_if_empty<BT>(&self, value: BT)where
BT: Borrow<T>,
pub fn set_if_empty<BT>(&self, value: BT)where
BT: Borrow<T>,
Saves argument to storage only if the storage is empty. Does nothing otherwise.
Sourcepub fn update<R, F: FnOnce(&mut T) -> R>(&self, f: F) -> R
pub fn update<R, F: FnOnce(&mut T) -> R>(&self, f: F) -> R
Syntactic sugar, to more compactly express a get, update and set in one line. Takes whatever lies in storage, apples the given closure and saves the final value back to storage. Propagates the return value of the given function.
pub fn replace<BT>(&self, new_value: BT) -> Twhere
BT: Borrow<T>,
Trait Implementations§
Source§impl<SA, T> StorageMapper<SA> for SingleValueMapper<SA, T, CurrentStorage>
impl<SA, T> StorageMapper<SA> for SingleValueMapper<SA, T, CurrentStorage>
Source§fn new(base_key: StorageKey<SA>) -> Self
fn new(base_key: StorageKey<SA>) -> Self
Will be called automatically by the
#[storage_mapper] annotation generated code.Source§impl<SA, T> StorageMapperFromAddress<SA> for SingleValueMapper<SA, T, ManagedAddress<SA>>
impl<SA, T> StorageMapperFromAddress<SA> for SingleValueMapper<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
Will be called automatically by the
#[storage_mapper_from_address]
annotation generated code.Source§impl<SA, T> TopEncodeMulti for SingleValueMapper<SA, T, CurrentStorage>
impl<SA, T> TopEncodeMulti for SingleValueMapper<SA, T, CurrentStorage>
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,
Version of
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,
Attempt to serialize the value to output.
Source§impl<SA, T> TypeAbi for SingleValueMapper<SA, T, CurrentStorage>
impl<SA, T> TypeAbi for SingleValueMapper<SA, T, CurrentStorage>
type Unmanaged = <T as TypeAbi>::Unmanaged
fn type_name() -> TypeName
fn type_name_rust() -> TypeName
Source§fn provide_type_descriptions<TDC: TypeDescriptionContainer>(
accumulator: &mut TDC,
)
fn provide_type_descriptions<TDC: TypeDescriptionContainer>( accumulator: &mut TDC, )
A type can provide more than its own name.
For instance, a struct can also provide the descriptions of the type of its fields.
TypeAbi doesn’t care for the exact accumulator type,
which is abstracted by the TypeDescriptionContainer trait.
fn type_names() -> TypeNames
impl<SA, T> TypeAbiFrom<SingleValueMapper<SA, T>> for PlaceholderOutput
impl<SA, T, R> TypeAbiFrom<SingleValueMapper<SA, T>> for SingleValue<R>
impl<SA, T> TypeAbiFrom<SingleValueMapper<SA, T>> for SingleValueMapper<SA, T, CurrentStorage>
Auto Trait Implementations§
impl<SA, T, A> Freeze for SingleValueMapper<SA, T, A>
impl<SA, T, A> RefUnwindSafe for SingleValueMapper<SA, T, A>where
A: RefUnwindSafe,
SA: RefUnwindSafe,
T: RefUnwindSafe,
<SA as HandleTypeInfo>::ManagedBufferHandle: RefUnwindSafe,
impl<SA, T, A> Send for SingleValueMapper<SA, T, A>
impl<SA, T, A> Sync for SingleValueMapper<SA, T, A>
impl<SA, T, A> Unpin for SingleValueMapper<SA, T, A>
impl<SA, T, A> UnsafeUnpin for SingleValueMapper<SA, T, A>
impl<SA, T, A> UnwindSafe for SingleValueMapper<SA, T, A>where
A: UnwindSafe,
SA: UnwindSafe,
T: UnwindSafe,
<SA as HandleTypeInfo>::ManagedBufferHandle: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more