Struct ink_storage::StorageVec
source · pub struct StorageVec<V: Packed, KeyType: StorageKey = AutoKey> { /* private fields */ }
Expand description
A vector of values (elements) directly on contract storage.
§Important
StorageVec requires its own pre-defined storage key where to store values. By
default, the is automatically calculated using AutoKey
during compilation. However, anyone can specify a storage key using
ManualKey
. Specifying the storage key can be helpful for
upgradeable contracts or you want to be resistant to future changes of storage key
calculation strategy.
§Differences between ink::prelude::vec::Vec
and StorageVec
Any Vec<T>
will exhibit Packed storage layout; where
StorageVec stores each value under it’s own storage key.
Hence, any read or write from or to a Vec
on storage will load
or store all of its elements.
This can be undesirable: The cost of reading or writing a single element grows linearly corresponding to the number of elements in the vector (its length). Additionally, the maximum capacity of the whole vector is limited by the size of the static buffer used during ABI encoding and decoding (default 16 KiB).
StorageVec on the other hand allows to access each element individually. Thus, it can theoretically grow to infinite size. However, we currently limit the length at 2 ^ 32 elements. In practice, even if the vector elements are single bytes, it’ll allow to store more than 4 GB data in blockchain storage.
§Caveats
Iterators are not provided. StorageVec is expected to be used to store a lot elements, where iterating through the elements would be rather inefficient (naturally, it is still possible to manually iterate over the elements using a loop).
For the same reason, operations which would require re-ordering stored elements are not supported. Examples include inserting and deleting elements at arbitrary positions or sorting elements.
The decision whether to use Vec<T>
or StorageVec can be seen as an
optimization problem with several factors:
- How large you expect the vector to grow
- The size of individual elements being stored
- How frequently reads, writes and iterations happen
For example, if a vector is expected to stay small but is frequently
iterated over. Choosing a Vec<T>
instead of StorageVec will be
preferred as individual storage reads are much more expensive as
opposed to retrieving and decoding the whole collection with a single
storage read.
§Storage Layout
At given StorageKey K
, the length of the StorageVec is hold.
Each element E
is then stored under a combination of the StorageVec
key K
and the elements index.
Given StorageVec under key K
, the storage key E
of the N
th
element is calculated as follows:
E = scale::Encode((K, N))
Implementations§
source§impl<V, KeyType> StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
impl<V, KeyType> StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
sourcepub fn len(&self) -> u32
pub fn len(&self) -> u32
Returns the number of elements in the vector, also referred to as its length.
The length is cached; subsequent calls (without writing to the vector) won’t trigger additional storage reads.
sourcepub fn push<T>(&mut self, value: &T)where
T: Storable + EncodeLike<V>,
pub fn push<T>(&mut self, value: &T)where
T: Storable + EncodeLike<V>,
Appends an element to the back of the vector.
§Panics
- If the vector is at capacity (max. of 2 ^ 32 elements).
- If the value overgrows the static buffer size.
- If there was already a value at the current index.
sourcepub fn try_push<T>(&mut self, value: &T) -> Result<(), Error>where
T: Storable + EncodeLike<V>,
pub fn try_push<T>(&mut self, value: &T) -> Result<(), Error>where
T: Storable + EncodeLike<V>,
Try to append an element to the back of the vector.
Returns:
Ok(())
if the value was inserted successfullyErr(_)
if the encoded value exceeds the static buffer size.
sourcepub fn pop(&mut self) -> Option<V>
pub fn pop(&mut self) -> Option<V>
Clears the last element from the storage and returns it.
Shrinks the length of the vector by one.
Returns None
if the vector is empty or if the last
element was already cleared from storage.
§Panics
- If the value overgrows the static buffer size.
sourcepub fn try_pop(&mut self) -> Option<Result<V, Error>>
pub fn try_pop(&mut self) -> Option<Result<V, Error>>
Try to clear and return the last element from storage.
Shrinks the length of the vector by one.
Returns None
if the vector is empty.
Returns
Some(Ok(_))
containing the value if it existed and was decoded successfully.
Some(Err(_))
if the value existed but its length exceeds the static buffer size.
None
if the vector is empty.
sourcepub fn peek(&self) -> Option<V>
pub fn peek(&self) -> Option<V>
Get a copy of the last element without removing it from storage.
§Panics
- If the value overgrows the static buffer size.
sourcepub fn try_peek(&self) -> Option<Result<V, Error>>
pub fn try_peek(&self) -> Option<Result<V, Error>>
Try to get a copy of the last element without removing it from storage.
Returns:
Some(Ok(_))
containing the value if it existed and was decoded successfully.
Some(Err(_))
if the value existed but its length exceeds the static buffer size.
None
if the vector is empty.
sourcepub fn get(&self, index: u32) -> Option<V>
pub fn get(&self, index: u32) -> Option<V>
Access an element at given index
.
Returns None
if there was no value at the index
.
§Panics
- If encoding the element exceeds the static buffer size.
sourcepub fn try_get(&self, index: u32) -> Option<Result<V>>
pub fn try_get(&self, index: u32) -> Option<Result<V>>
Try to access an element at given index
.
Returns:
Some(Ok(_))
containing the value if it existed and was decoded successfully.Some(Err(_))
if the value existed but its length exceeds the static buffer size.None
if there was no value atindex
.
sourcepub fn set<T>(&mut self, index: u32, value: &T) -> Option<u32>where
T: Storable + EncodeLike<V>,
pub fn set<T>(&mut self, index: u32, value: &T) -> Option<u32>where
T: Storable + EncodeLike<V>,
Set the value
at given index
.
§Panics
- If the index is out of bounds.
- If decoding the element exceeds the static buffer size.
sourcepub fn try_set<T>(
&mut self,
index: u32,
value: &T,
) -> Result<Option<u32>, Error>where
T: Storable + EncodeLike<V>,
pub fn try_set<T>(
&mut self,
index: u32,
value: &T,
) -> Result<Option<u32>, Error>where
T: Storable + EncodeLike<V>,
Try to set the value
at given index
.
Returns:
Ok(Some(_))
if the value was inserted successfully, containing the size in bytes of the pre-existing value at the specified key if any.Ok(None)
if the insert was successful but there was no pre-existing value.- Err(
ink_env::Error::BufferTooSmall
) if the encoded value exceeds the static buffer size - Err(
ink_env::Error::ReturnError
([ink_env::ReturnErrorCode::KeyNotFound
])) if theindex
is out of bounds.
§Panics
Panics if index
exceeds the length of the vector.
Trait Implementations§
source§impl<V, KeyType> Debug for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
impl<V, KeyType> Debug for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
source§impl<V, KeyType> Default for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
impl<V, KeyType> Default for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
source§impl<V, KeyType> FromIterator<V> for StorageVec<V, KeyType>where
V: Packed + EncodeLike<V>,
KeyType: StorageKey,
impl<V, KeyType> FromIterator<V> for StorageVec<V, KeyType>where
V: Packed + EncodeLike<V>,
KeyType: StorageKey,
source§fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self
source§impl<V, KeyType> Storable for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
impl<V, KeyType> Storable for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
source§fn encode<T: Output + ?Sized>(&self, _dest: &mut T)
fn encode<T: Output + ?Sized>(&self, _dest: &mut T)
source§fn decode<I: Input>(_input: &mut I) -> Result<Self, Error>
fn decode<I: Input>(_input: &mut I) -> Result<Self, Error>
source§fn encoded_size(&self) -> usize
fn encoded_size(&self) -> usize
source§impl<V, Key, InnerKey> StorableHint<Key> for StorageVec<V, InnerKey>
impl<V, Key, InnerKey> StorableHint<Key> for StorageVec<V, InnerKey>
§type Type = StorageVec<V, Key>
type Type = StorageVec<V, Key>
§type PreferredKey = InnerKey
type PreferredKey = InnerKey
source§impl<V, KeyType> StorageKey for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
impl<V, KeyType> StorageKey for StorageVec<V, KeyType>where
V: Packed,
KeyType: StorageKey,
source§impl<V, KeyType> StorageLayout for StorageVec<V, KeyType>
impl<V, KeyType> StorageLayout for StorageVec<V, KeyType>
source§impl<V, KeyType> TypeInfo for StorageVec<V, KeyType>
impl<V, KeyType> TypeInfo for StorageVec<V, KeyType>
Auto Trait Implementations§
impl<V, KeyType = AutoKey> !Freeze for StorageVec<V, KeyType>
impl<V, KeyType = AutoKey> !RefUnwindSafe for StorageVec<V, KeyType>
impl<V, KeyType> Send for StorageVec<V, KeyType>
impl<V, KeyType = AutoKey> !Sync for StorageVec<V, KeyType>
impl<V, KeyType> Unpin for StorageVec<V, KeyType>
impl<V, KeyType> UnwindSafe for StorageVec<V, KeyType>
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
§impl<T> SaturatedConversion for T
impl<T> SaturatedConversion for T
§fn saturated_from<T>(t: T) -> Selfwhere
Self: UniqueSaturatedFrom<T>,
fn saturated_from<T>(t: T) -> Selfwhere
Self: UniqueSaturatedFrom<T>,
§fn saturated_into<T>(self) -> Twhere
Self: UniqueSaturatedInto<T>,
fn saturated_into<T>(self) -> Twhere
Self: UniqueSaturatedInto<T>,
T
. Read more§impl<T, S> UniqueSaturatedInto<T> for S
impl<T, S> UniqueSaturatedInto<T> for S
§fn unique_saturated_into(self) -> T
fn unique_saturated_into(self) -> T
T
.