pub struct StateMap<K, V, S> { /* private fields */ }
Expand description

A high-level map based on the low-level key-value store, which is the interface provided by the chain.

In most situations, this collection should be preferred over BTreeMap and HashMap since it will be more efficient to lookup and update since costs to lookup and update will grow very slowly with the size of the collection. In contrast, using BTreeMap and HashMap almost always entails their serialization, which is linear in the size of the collection.

The cost of updates to the map are dependent on the length of K (in bytes) and the size of the data stored (V). Short keys are therefore ideal.

New maps can be constructed using the new_map method on the StateBuilder.

/// In an init method:
let mut map1 = state_builder.new_map();

/// In a receive method:
let mut map2 = host.state_builder().new_map();

§Type parameters

The map StateMap<K, V, S> is parametrized by the type of keys K, the type of values V and the type of the low-level state S. In line with other Rust collections, e.g., BTreeMap and HashMap constructing the statemap via new_map does not require anything specific from K and V. However most operations do require that K is serializable and V can be stored and loaded in the context of the low-level state S.

This concretely means that K must implement Serialize and V has to implement Serial and DeserialWithState<S>. In practice, this means that keys must be flat, meaning that it cannot have any references to the low-level state. This is almost all types, except StateBox, StateMap and StateSet and types containing these.

However values may contain references to the low-level state, in particular maps may be nested.

§Low-level state S

The type parameter S is extra compared to usual Rust collections. As mentioned above it specifies the low-level state implementation. This library provides two such implementations. The “external” one (StateApi), which is the implementation supported by external host functions provided by the chain, and a test one. The latter one is only useful for testing with the deprecated test_infrastructure module.

In user code this type parameter should generally be treated as boilerplate, and contract entrypoints should always be stated in terms of a generic type S that implements HasStateApi and defaults to StateApi, unless you intend to use the deprecated testing library.

§Example
#[derive(Serial, DeserialWithState)]
#[concordium(state_parameter = "S")]
struct MyState<S: HasStateApi = StateApi> {
    inner: StateMap<u64, u64, S>,
}
#[init(contract = "mycontract")]
fn contract_init(_ctx: &InitContext, state_builder: &mut StateBuilder) -> InitResult<MyState> {
    Ok(MyState {
        inner: state_builder.new_map(),
    })
}

#[receive(contract = "mycontract", name = "receive", return_value = "Option<u64>")]
fn contract_receive(
    _ctx: &ReceiveContext,
    host: &Host<MyState>, // the same low-level state must be propagated throughout
) -> ReceiveResult<Option<u64>> {
    let state = host.state();
    Ok(state.inner.get(&0).map(|v| *v))
}

§Caution

StateMaps must be explicitly deleted when they are no longer needed, otherwise they will remain in the contract’s state, albeit unreachable.

struct MyState<S: HasStateApi = StateApi> {
    inner: StateMap<u64, u64, S>,
}
fn incorrect_replace(state_builder: &mut StateBuilder, state: &mut MyState) {
    // The following is incorrect. The old value of `inner` is not properly deleted.
    // from the state.
    state.inner = state_builder.new_map(); // ⚠️
}

Instead, either the map should be cleared or explicitly deleted.

fn correct_replace(state_builder: &mut StateBuilder, state: &mut MyState) {
    state.inner.clear_flat();
}

Or alternatively

fn correct_replace(state_builder: &mut StateBuilder, state: &mut MyState) {
    let old_map = mem::replace(&mut state.inner, state_builder.new_map());
    old_map.delete()
}

Implementations§

source§

impl<K, V, S> StateMap<K, V, S>

source

pub fn get(&self, key: &K) -> Option<StateRef<'_, V>>

Lookup the value with the given key. Return None if there is no value with the given key.

source

pub fn get_mut(&mut self, key: &K) -> Option<StateRefMut<'_, V, S>>

Lookup a mutable reference to the value with the given key. Return None if there is no value with the given key.

source

pub fn insert(&mut self, key: K, value: V) -> Option<V>

Inserts the value with the given key. If a value already exists at the given key it is replaced and the old value is returned.

Caution: If Option<V> is to be deleted and contains a data structure prefixed with State (such as StateBox or StateMap), then it is important to call Deletable::delete on the value returned when you’re finished with it. Otherwise, it will remain in the contract state.

source

pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S>

Get an entry for the given key.

source

pub fn is_empty(&self) -> bool

Return true if the map contains no elements.

source

pub fn clear(&mut self)
where V: Deletable,

Clears the map, removing all key-value pairs. This also includes values pointed at, if V, for example, is a StateBox. If applicable use clear_flat instead.

source

pub fn clear_flat(&mut self)
where V: Deserial,

Clears the map, removing all key-value pairs. This should be used over clear if it is applicable. It avoids recursive deletion of values since the values are required to be flat.

Unfortunately it is not possible to automatically choose between these implementations. Once Rust gets trait specialization then this might be possible.

source

pub fn remove_and_get(&mut self, key: &K) -> Option<V>

Remove a key from the map, returning the value at the key if the key was previously in the map.

Caution: If V is a StateBox, StateMap, then it is important to call Deletable::delete on the value returned when you’re finished with it. Otherwise, it will remain in the contract state.

source

pub fn remove(&mut self, key: &K)
where V: Deletable,

Remove a key from the map. This also deletes the value in the state.

source§

impl<K, V, S> StateMap<K, V, S>
where S: HasStateApi,

source

pub fn iter(&self) -> StateMapIter<'_, K, V, S>

Get an iterator over the key-value pairs of the map. The iterator returns values in increasing order of keys, where keys are ordered lexicographically via their serializations.

source

pub fn iter_mut(&mut self) -> StateMapIterMut<'_, K, V, S>

Like iter, but allows modifying the values during iteration.

Trait Implementations§

source§

impl<K: Debug, V: Debug, S: Debug> Debug for StateMap<K, V, S>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<K, V, S> Deletable for StateMap<K, V, S>

source§

fn delete(self)

Delete all items that this type owns in the state.
source§

impl<K, V, S> DeserialWithState<S> for StateMap<K, V, S>
where S: HasStateApi,

source§

fn deserial_with_state<R: Read>(state: &S, source: &mut R) -> ParseResult<Self>

Attempt to read a structure from a given source and state, failing if an error occurs during deserialization or reading.
source§

impl<K, V, S> Serial for StateMap<K, V, S>

source§

fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err>

Attempt to write the structure into the provided writer, failing if only part of the structure could be written. Read more

Auto Trait Implementations§

§

impl<K, V, S> Freeze for StateMap<K, V, S>
where S: Freeze,

§

impl<K, V, S> RefUnwindSafe for StateMap<K, V, S>

§

impl<K, V, S> Send for StateMap<K, V, S>
where S: Send, K: Send, V: Send,

§

impl<K, V, S> Sync for StateMap<K, V, S>
where S: Sync, K: Sync, V: Sync,

§

impl<K, V, S> Unpin for StateMap<K, V, S>
where S: Unpin, K: Unpin, V: Unpin,

§

impl<K, V, S> UnwindSafe for StateMap<K, V, S>
where S: UnwindSafe, K: UnwindSafe, V: UnwindSafe,

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, U> TryFrom<U> for T
where U: Into<T>,

§

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

§

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.