Skip to main content

SingleValueMapper

Struct SingleValueMapper 

Source
pub struct SingleValueMapper<SA, T, A = CurrentStorage>
where SA: StorageMapperApi, A: StorageAddress<SA>, T: TopEncode + TopDecode + 'static,
{ /* 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 type T

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>
where SA: StorageMapperApi, A: StorageAddress<SA>, T: TopEncode + TopDecode,

Source

pub fn get(&self) -> T

Retrieves current value from storage.

Source

pub fn is_empty(&self) -> bool

Returns whether the storage managed by this mapper is empty.

Source

pub fn raw_byte_length(&self) -> usize

Source§

impl<SA, T> SingleValueMapper<SA, T, CurrentStorage>

Source

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.

Source

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.

Source

pub fn clear(&self)

Clears the storage for this mapper.

Source

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.

Source

pub fn take(&self) -> T

Takes the value out of the storage, clearing it in the process.

Source

pub fn replace<BT>(&self, new_value: BT) -> T
where BT: Borrow<T>,

Trait Implementations§

Source§

impl<SA, T> StorageMapper<SA> for SingleValueMapper<SA, T, CurrentStorage>

Source§

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>>

Source§

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>

Source§

fn multi_encode_or_handle_err<O, H>( &self, output: &mut O, h: H, ) -> Result<(), H::HandledErr>

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>

Attempt to serialize the value to output.
Source§

impl<SA, T> TypeAbi for SingleValueMapper<SA, T, CurrentStorage>

Source§

type Unmanaged = <T as TypeAbi>::Unmanaged

Source§

fn type_name() -> TypeName

The type name, as it shows up in the ABI.
Source§

fn type_name_rust() -> TypeName

The type name as it shows up in Rust code. Used for proxies. Read more
Source§

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.
Source§

fn type_names() -> TypeNames

Source§

fn type_name_specific() -> Option<TypeName>

Specific name to be optionally added to the ABI. Read more
Source§

impl<SA, T> TypeAbiFrom<SingleValueMapper<SA, T>> for PlaceholderOutput

Source§

impl<SA, T, R> TypeAbiFrom<SingleValueMapper<SA, T>> for SingleValue<R>

Source§

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>

§

impl<SA, T, A> Send for SingleValueMapper<SA, T, A>
where A: Send, SA: Send, T: Send, <SA as HandleTypeInfo>::ManagedBufferHandle: Send,

§

impl<SA, T, A> Sync for SingleValueMapper<SA, T, A>
where A: Sync, SA: Sync, T: Sync, <SA as HandleTypeInfo>::ManagedBufferHandle: Sync,

§

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>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<O, T> ProxyArg<O> for T
where O: TypeAbiFrom<T>, T: TopEncodeMulti,

Source§

impl<T, U> TypeAbiFrom<TypeAbiUniversalInput<T>> for U