multiversx_sc/storage/
storage_get_from_address.rs

1use crate::{
2    api::{
3        const_handles, use_raw_handle, ErrorApi, HandleConstraints, ManagedBufferApiImpl,
4        ManagedTypeApi, StorageReadApi, StorageReadApiImpl,
5    },
6    codec::*,
7    types::{
8        BigInt, BigUint, ManagedAddress, ManagedBuffer, ManagedBufferNestedDecodeInput, ManagedRef,
9        ManagedType,
10    },
11};
12use alloc::boxed::Box;
13use unwrap_infallible::UnwrapInfallible;
14
15use super::{StorageGetErrorHandler, StorageKey};
16
17struct StorageGetFromAddressInput<'k, A>
18where
19    A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static,
20{
21    addr: ManagedRef<'k, A, ManagedAddress<A>>,
22    key: ManagedRef<'k, A, StorageKey<A>>,
23}
24
25impl<'k, A> StorageGetFromAddressInput<'k, A>
26where
27    A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static,
28{
29    #[inline]
30    fn new(
31        addr: ManagedRef<'k, A, ManagedAddress<A>>,
32        key: ManagedRef<'k, A, StorageKey<A>>,
33    ) -> Self {
34        StorageGetFromAddressInput { addr, key }
35    }
36
37    fn to_managed_buffer(&self) -> ManagedBuffer<A> {
38        unsafe {
39            let result = ManagedBuffer::new_uninit();
40            A::storage_read_api_impl().storage_load_from_address(
41                self.addr.get_handle(),
42                self.key.buffer.get_handle(),
43                result.get_handle(),
44            );
45            result
46        }
47    }
48
49    fn to_big_uint(&self) -> BigUint<A> {
50        BigUint::from_bytes_be_buffer(&self.to_managed_buffer())
51    }
52
53    fn to_big_int(&self) -> BigInt<A> {
54        BigInt::from_signed_bytes_be_buffer(&self.to_managed_buffer())
55    }
56
57    fn load_len_managed_buffer(&self) -> usize {
58        let value_handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1);
59        A::storage_read_api_impl().storage_load_from_address(
60            self.addr.get_handle(),
61            self.key.buffer.get_handle(),
62            value_handle.clone(),
63        );
64
65        A::managed_type_impl().mb_len(value_handle)
66    }
67}
68
69impl<A> TopDecodeInput for StorageGetFromAddressInput<'_, A>
70where
71    A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static,
72{
73    type NestedBuffer = ManagedBufferNestedDecodeInput<A>;
74
75    fn byte_len(&self) -> usize {
76        self.load_len_managed_buffer()
77    }
78
79    fn into_boxed_slice_u8(self) -> Box<[u8]> {
80        self.to_managed_buffer().to_boxed_bytes().into_box()
81    }
82
83    #[inline]
84    fn into_max_size_buffer<H, const MAX_LEN: usize>(
85        self,
86        buffer: &mut [u8; MAX_LEN],
87        h: H,
88    ) -> Result<&[u8], H::HandledErr>
89    where
90        H: DecodeErrorHandler,
91    {
92        self.to_managed_buffer().into_max_size_buffer(buffer, h)
93    }
94
95    #[inline]
96    fn into_max_size_buffer_align_right<H, const MAX_LEN: usize>(
97        self,
98        buffer: &mut [u8; MAX_LEN],
99        h: H,
100    ) -> Result<usize, H::HandledErr>
101    where
102        H: DecodeErrorHandler,
103    {
104        self.to_managed_buffer()
105            .into_max_size_buffer_align_right(buffer, h)
106    }
107
108    #[inline]
109    fn into_i64<H>(self, h: H) -> Result<i64, H::HandledErr>
110    where
111        H: DecodeErrorHandler,
112    {
113        self.to_managed_buffer().into_i64(h)
114    }
115
116    #[inline]
117    fn supports_specialized_type<T: TryStaticCast>() -> bool {
118        T::type_eq::<ManagedBuffer<A>>() || T::type_eq::<BigUint<A>>() || T::type_eq::<BigInt<A>>()
119    }
120
121    #[inline]
122    fn into_specialized<T, H>(self, h: H) -> Result<T, H::HandledErr>
123    where
124        T: TryStaticCast,
125        H: DecodeErrorHandler,
126    {
127        if let Some(result) = try_execute_then_cast(|| self.to_managed_buffer()) {
128            Ok(result)
129        } else if let Some(result) = try_execute_then_cast(|| self.to_big_uint()) {
130            Ok(result)
131        } else if let Some(result) = try_execute_then_cast(|| self.to_big_int()) {
132            Ok(result)
133        } else {
134            Err(h.handle_error(DecodeError::UNSUPPORTED_OPERATION))
135        }
136    }
137
138    fn into_nested_buffer(self) -> Self::NestedBuffer {
139        ManagedBufferNestedDecodeInput::new(self.to_managed_buffer())
140    }
141}
142
143pub fn storage_get_from_address<A, T>(
144    addr: ManagedRef<'_, A, ManagedAddress<A>>,
145    key: ManagedRef<'_, A, StorageKey<A>>,
146) -> T
147where
148    T: TopDecode,
149    A: StorageReadApi + ManagedTypeApi + ErrorApi,
150{
151    let handle = key.get_handle().get_raw_handle_unchecked();
152    T::top_decode_or_handle_err(
153        StorageGetFromAddressInput::new(addr, key),
154        StorageGetErrorHandler::<A>::new(handle),
155    )
156    .unwrap_infallible()
157}
158
159/// Useful for storage mappers.
160/// Also calls to it generated by macro.
161pub fn storage_get_len_from_address<A>(
162    addr: ManagedRef<'_, A, ManagedAddress<A>>,
163    key: ManagedRef<'_, A, StorageKey<A>>,
164) -> usize
165where
166    A: StorageReadApi + ManagedTypeApi + ErrorApi,
167{
168    let input = StorageGetFromAddressInput::new(addr, key);
169    input.load_len_managed_buffer()
170}