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>where
V: Packed,
Key: StorageKey,
InnerKey: StorageKey,
impl<V, Key, InnerKey> StorableHint<Key> for StorageVec<V, InnerKey>where
V: Packed,
Key: StorageKey,
InnerKey: StorageKey,
Source§type Type = StorageVec<V, Key>
type Type = StorageVec<V, Key>
Source§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>where
V: Packed + StorageLayout + TypeInfo + 'static,
KeyType: StorageKey + TypeInfo + 'static,
impl<V, KeyType> StorageLayout for StorageVec<V, KeyType>where
V: Packed + StorageLayout + TypeInfo + 'static,
KeyType: StorageKey + TypeInfo + 'static,
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> CheckedConversion for T
impl<T> CheckedConversion for T
§fn checked_from<T>(t: T) -> Option<Self>where
Self: TryFrom<T>,
fn checked_from<T>(t: T) -> Option<Self>where
Self: TryFrom<T>,
§fn checked_into<T>(self) -> Option<T>where
Self: TryInto<T>,
fn checked_into<T>(self) -> Option<T>where
Self: TryInto<T>,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<Src, Dest> IntoTuple<Dest> for Srcwhere
Dest: FromTuple<Src>,
impl<Src, Dest> IntoTuple<Dest> for Srcwhere
Dest: FromTuple<Src>,
fn into_tuple(self) -> Dest
§impl<T> IsType<T> for T
impl<T> IsType<T> for T
§impl<T, Outer> IsWrappedBy<Outer> for T
impl<T, Outer> IsWrappedBy<Outer> for T
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§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> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.§impl<T> TryConv for T
impl<T> TryConv for T
§impl<T, U> TryIntoKey<U> for Twhere
U: TryFromKey<T>,
impl<T, U> TryIntoKey<U> for Twhere
U: TryFromKey<T>,
type Error = <U as TryFromKey<T>>::Error
fn try_into_key(self) -> Result<U, <U as TryFromKey<T>>::Error>
§impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
§fn unchecked_into(self) -> T
fn unchecked_into(self) -> T
unchecked_from
.§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
.