Skip to main content

multiversx_sc/contract_base/wrappers/
storage_raw_wrapper.rs

1use core::marker::PhantomData;
2
3use unwrap_infallible::UnwrapInfallible;
4
5use crate::api::HandleConstraints;
6use crate::codec::{TopDecode, TopEncode};
7
8use crate::{
9    api::{
10        ErrorApi, ManagedTypeApi, StorageReadApi, StorageReadApiImpl, StorageWriteApi,
11        const_handles::MBUF_TEMPORARY_1, use_raw_handle,
12    },
13    storage::StorageKey,
14    storage_get,
15    storage_get::StorageGetErrorHandler,
16    storage_set,
17    types::{ManagedAddress, ManagedBuffer, ManagedType},
18};
19
20#[derive(Default)]
21pub struct StorageRawWrapper<A>
22where
23    A: StorageReadApi + ManagedTypeApi + ErrorApi,
24{
25    _phantom: PhantomData<A>,
26}
27
28impl<A> StorageRawWrapper<A>
29where
30    A: StorageReadApi + StorageWriteApi + ManagedTypeApi + ErrorApi,
31{
32    pub fn new() -> Self {
33        StorageRawWrapper {
34            _phantom: PhantomData,
35        }
36    }
37
38    /// Reads storage from the given key, and deserializes the value to the provided type.
39    ///
40    /// Use only if really necessary, storage mappers should be preferred.
41    #[inline]
42    pub fn read<K, V>(&self, storage_key: K) -> V
43    where
44        K: Into<StorageKey<A>>,
45        V: TopDecode,
46    {
47        let key: StorageKey<A> = storage_key.into();
48        storage_get(key.as_ref())
49    }
50
51    /// Reads storage from another address (usually a smart contract),
52    /// from the given key, and deserializes the value to the provided type.
53    ///
54    /// This is a synchronous call, so it only works when
55    /// both the current contract and the destination are in the same shard.
56    pub fn read_from_address<K, V>(&self, address: &ManagedAddress<A>, storage_key: K) -> V
57    where
58        K: Into<StorageKey<A>>,
59        V: TopDecode,
60    {
61        let key: StorageKey<A> = storage_key.into();
62        let result_buffer =
63            unsafe { ManagedBuffer::<A>::from_handle(use_raw_handle(MBUF_TEMPORARY_1)) };
64        A::storage_read_api_impl().storage_load_from_address(
65            address.get_handle(),
66            key.get_handle(),
67            result_buffer.get_handle(),
68        );
69
70        V::top_decode_or_handle_err(
71            result_buffer,
72            StorageGetErrorHandler::<A>::new(key.get_handle().get_raw_handle_unchecked()),
73        )
74        .unwrap_infallible()
75    }
76
77    /// Write a serializable value to storage under the given key
78    ///
79    /// Use only if really necessary, storage mappers should be preferred.
80    #[inline]
81    pub fn write<K, V>(&self, storage_key: K, value: &V)
82    where
83        K: Into<StorageKey<A>>,
84        V: TopEncode,
85    {
86        let key: StorageKey<A> = storage_key.into();
87        storage_set(key.as_ref(), value);
88    }
89}