dharitri_sc/storage/
storage_get.rs

1use core::{convert::Infallible, marker::PhantomData};
2
3use crate::{
4    api::{
5        const_handles, use_raw_handle, ErrorApi, ErrorApiImpl, HandleConstraints,
6        ManagedBufferApiImpl, ManagedTypeApi, StorageReadApi, StorageReadApiImpl,
7    },
8    codec::*,
9    err_msg,
10    types::{
11        BigInt, BigUint, ManagedBuffer, ManagedBufferNestedDecodeInput, ManagedRef, ManagedType,
12    },
13};
14use alloc::boxed::Box;
15use unwrap_infallible::UnwrapInfallible;
16
17use super::StorageKey;
18
19struct StorageGetInput<'k, A>
20where
21    A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static,
22{
23    key: ManagedRef<'k, A, StorageKey<A>>,
24}
25
26impl<'k, A> StorageGetInput<'k, A>
27where
28    A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static,
29{
30    #[inline]
31    fn new(key: ManagedRef<'k, A, StorageKey<A>>) -> Self {
32        StorageGetInput { key }
33    }
34
35    fn to_managed_buffer(&self) -> ManagedBuffer<A> {
36        unsafe {
37            let result = ManagedBuffer::new_uninit();
38            A::storage_read_api_impl()
39                .storage_load_managed_buffer_raw(self.key.buffer.get_handle(), result.get_handle());
40            result
41        }
42    }
43
44    fn to_big_uint(&self) -> BigUint<A> {
45        BigUint::from_bytes_be_buffer(&self.to_managed_buffer())
46    }
47
48    fn to_big_int(&self) -> BigInt<A> {
49        BigInt::from_signed_bytes_be_buffer(&self.to_managed_buffer())
50    }
51
52    fn load_len_managed_buffer(&self) -> usize {
53        let value_handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1);
54        A::storage_read_api_impl()
55            .storage_load_managed_buffer_raw(self.key.buffer.get_handle(), value_handle.clone());
56        A::managed_type_impl().mb_len(value_handle)
57    }
58}
59
60impl<A> TopDecodeInput for StorageGetInput<'_, A>
61where
62    A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static,
63{
64    type NestedBuffer = ManagedBufferNestedDecodeInput<A>;
65
66    fn byte_len(&self) -> usize {
67        self.load_len_managed_buffer()
68    }
69
70    fn into_boxed_slice_u8(self) -> Box<[u8]> {
71        self.to_managed_buffer().to_boxed_bytes().into_box()
72    }
73
74    #[inline]
75    fn into_max_size_buffer<H, const MAX_LEN: usize>(
76        self,
77        buffer: &mut [u8; MAX_LEN],
78        h: H,
79    ) -> Result<&[u8], H::HandledErr>
80    where
81        H: DecodeErrorHandler,
82    {
83        self.to_managed_buffer().into_max_size_buffer(buffer, h)
84    }
85
86    #[inline]
87    fn into_max_size_buffer_align_right<H, const MAX_LEN: usize>(
88        self,
89        buffer: &mut [u8; MAX_LEN],
90        h: H,
91    ) -> Result<usize, H::HandledErr>
92    where
93        H: DecodeErrorHandler,
94    {
95        self.to_managed_buffer()
96            .into_max_size_buffer_align_right(buffer, h)
97    }
98
99    #[inline]
100    fn into_i64<H>(self, h: H) -> Result<i64, H::HandledErr>
101    where
102        H: DecodeErrorHandler,
103    {
104        self.to_managed_buffer().into_i64(h)
105    }
106
107    #[inline]
108    fn supports_specialized_type<T: TryStaticCast>() -> bool {
109        T::type_eq::<ManagedBuffer<A>>() || T::type_eq::<BigUint<A>>() || T::type_eq::<BigInt<A>>()
110    }
111
112    #[inline]
113    fn into_specialized<T, H>(self, h: H) -> Result<T, H::HandledErr>
114    where
115        T: TryStaticCast,
116        H: DecodeErrorHandler,
117    {
118        if let Some(result) = try_execute_then_cast(|| self.to_managed_buffer()) {
119            Ok(result)
120        } else if let Some(result) = try_execute_then_cast(|| self.to_big_uint()) {
121            Ok(result)
122        } else if let Some(result) = try_execute_then_cast(|| self.to_big_int()) {
123            Ok(result)
124        } else {
125            Err(h.handle_error(DecodeError::UNSUPPORTED_OPERATION))
126        }
127    }
128
129    fn into_nested_buffer(self) -> Self::NestedBuffer {
130        ManagedBufferNestedDecodeInput::new(self.to_managed_buffer())
131    }
132}
133
134pub fn storage_get<A, T>(key: ManagedRef<'_, A, StorageKey<A>>) -> T
135where
136    T: TopDecode,
137    A: StorageReadApi + ManagedTypeApi + ErrorApi,
138{
139    let handle = key.get_handle().get_raw_handle_unchecked();
140    T::top_decode_or_handle_err(
141        StorageGetInput::new(key),
142        StorageGetErrorHandler::<A>::new(handle),
143    )
144    .unwrap_infallible()
145}
146
147/// Useful for storage mappers.
148/// Also calls to it generated by macro.
149pub fn storage_get_len<A>(key: ManagedRef<'_, A, StorageKey<A>>) -> usize
150where
151    A: StorageReadApi + ManagedTypeApi + ErrorApi,
152{
153    let input = StorageGetInput::new(key);
154    input.load_len_managed_buffer()
155}
156
157/// Will immediately end the execution when encountering the first decode error, via `signal_error`.
158/// Because its handled error type is the never type, when compiled,
159/// the codec will return the value directly, without wrapping it in a Result.
160#[derive(Clone)]
161pub(crate) struct StorageGetErrorHandler<M>
162where
163    M: ManagedTypeApi + ErrorApi,
164{
165    _phantom: PhantomData<M>,
166    key: i32,
167}
168
169impl<M> Copy for StorageGetErrorHandler<M> where M: ManagedTypeApi + ErrorApi {}
170
171impl<M> StorageGetErrorHandler<M>
172where
173    M: ManagedTypeApi + ErrorApi,
174{
175    #[inline]
176    pub fn new(key: i32) -> Self {
177        StorageGetErrorHandler {
178            _phantom: PhantomData,
179            key,
180        }
181    }
182}
183
184impl<M> DecodeErrorHandler for StorageGetErrorHandler<M>
185where
186    M: ManagedTypeApi + ErrorApi,
187{
188    type HandledErr = Infallible;
189
190    fn handle_error(&self, err: DecodeError) -> Self::HandledErr {
191        let mut message_buffer =
192            ManagedBuffer::<M>::new_from_bytes(err_msg::STORAGE_DECODE_ERROR_1.as_bytes());
193        M::managed_type_impl().mb_append(message_buffer.get_handle(), self.key.into());
194        message_buffer.append_bytes(err_msg::STORAGE_DECODE_ERROR_2.as_bytes());
195        message_buffer.append_bytes(err.message_bytes());
196        M::error_api_impl().signal_error_from_buffer(message_buffer.get_handle())
197    }
198}