dharitri_sc/types/managed/multi_value/
multi_value_encoded.rs

1use unwrap_infallible::UnwrapInfallible;
2
3use crate::codec::multi_types::MultiValueVec;
4use crate::{
5    abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
6    api::{ErrorApi, ManagedTypeApi},
7    codec::{
8        try_cast_execute_or_else, DecodeErrorHandler, EncodeErrorHandler, TopDecode,
9        TopDecodeMulti, TopDecodeMultiInput, TopDecodeMultiLength, TopEncode, TopEncodeMulti,
10        TopEncodeMultiOutput,
11    },
12    contract_base::{ExitCodecErrorHandler, ManagedSerializer},
13    err_msg,
14    types::{ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVec, ManagedVecItem},
15};
16use core::{iter::FromIterator, marker::PhantomData};
17
18use super::MultiValueEncodedIterator;
19
20/// A multi-value container, that keeps raw values as ManagedBuffer
21/// It allows encoding and decoding of multi-values.
22///
23/// Since items are kept raw, the item type does not need to implement `ManagedVecItem`.
24///
25/// Behavior:
26/// - It is lazy when decoding, in that it keeps them raw and will not decode the values until they are requested.
27/// - It is eager when encoding, items are serialized before being added to this structure.
28///
29/// Since it can contain multi-values, the number of actual items it contains cannot be determined without fully decoding.
30///
31#[derive(Clone, Default, Debug, PartialEq)]
32pub struct MultiValueEncoded<M, T>
33where
34    M: ManagedTypeApi,
35{
36    pub(super) raw_buffers: ManagedVec<M, ManagedBuffer<M>>,
37    _phantom: PhantomData<T>,
38}
39
40#[deprecated(
41    since = "0.29.0",
42    note = "Alias kept for backwards compatibility. Replace with `MultiValueEncoded`"
43)]
44pub type ManagedVarArgs<M, T> = MultiValueEncoded<M, T>;
45
46#[deprecated(
47    since = "0.29.0",
48    note = "Alias kept for backwards compatibility. Replace with `MultiValueEncoded`"
49)]
50pub type ManagedMultiResultVec<M, T> = MultiValueEncoded<M, T>;
51
52impl<M, T> MultiValueEncoded<M, T>
53where
54    M: ManagedTypeApi,
55{
56    #[inline]
57    fn from_raw_vec(raw_buffers: ManagedVec<M, ManagedBuffer<M>>) -> Self {
58        MultiValueEncoded {
59            raw_buffers,
60            _phantom: PhantomData,
61        }
62    }
63
64    #[inline]
65    pub fn new() -> Self {
66        MultiValueEncoded::from_raw_vec(ManagedVec::new())
67    }
68}
69
70impl<M, T> MultiValueEncoded<M, T>
71where
72    M: ManagedTypeApi + ErrorApi,
73    T: TopEncodeMulti,
74{
75    pub fn push(&mut self, item: T) {
76        item.multi_encode_or_handle_err(
77            &mut self.raw_buffers,
78            ExitCodecErrorHandler::<M>::from(err_msg::SERIALIZER_ENCODE_ERROR),
79        )
80        .unwrap_infallible()
81    }
82}
83
84impl<M, T> From<ManagedVec<M, T>> for MultiValueEncoded<M, T>
85where
86    M: ManagedTypeApi,
87    T: ManagedVecItem + TopEncode + 'static,
88{
89    #[inline]
90    fn from(v: ManagedVec<M, T>) -> Self {
91        try_cast_execute_or_else(
92            v,
93            MultiValueEncoded::from_raw_vec,
94            MultiValueEncoded::from_iter,
95        )
96    }
97}
98
99impl<M, T> MultiValueEncoded<M, T>
100where
101    M: ManagedTypeApi,
102{
103    pub fn to_arg_buffer(&self) -> ManagedArgBuffer<M> {
104        unsafe { ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) }
105    }
106}
107
108impl<M> MultiValueEncoded<M, ManagedBuffer<M>>
109where
110    M: ManagedTypeApi,
111{
112    pub fn into_vec_of_buffers(self) -> ManagedVec<M, ManagedBuffer<M>> {
113        self.raw_buffers
114    }
115}
116
117impl<M, T> MultiValueEncoded<M, T>
118where
119    M: ManagedTypeApi + ErrorApi,
120{
121    /// Length of the underlying data.
122    ///
123    /// Note:
124    /// In general, it is **not** the number of items that can be decoded.
125    /// It is the same as `len()` only for single encode items.
126    #[inline]
127    pub fn raw_len(&self) -> usize {
128        self.raw_buffers.len()
129    }
130
131    pub fn is_empty(&self) -> bool {
132        self.raw_buffers.is_empty()
133    }
134}
135
136impl<M, T> IntoIterator for MultiValueEncoded<M, T>
137where
138    M: ManagedTypeApi + ErrorApi,
139    T: TopDecodeMulti,
140{
141    type Item = T;
142    type IntoIter = MultiValueEncodedIterator<M, T>;
143    fn into_iter(self) -> Self::IntoIter {
144        MultiValueEncodedIterator::new(self.raw_buffers)
145    }
146}
147
148impl<M, T> MultiValueEncoded<M, T>
149where
150    M: ManagedTypeApi + ErrorApi,
151    T: TopDecodeMultiLength,
152{
153    /// Number of items. Only available for multi-encode items.
154    #[inline]
155    pub fn len(&self) -> usize {
156        self.raw_len() / T::get_len()
157    }
158}
159
160impl<M, T> MultiValueEncoded<M, T>
161where
162    M: ManagedTypeApi + ErrorApi,
163    T: ManagedVecItem + TopDecode,
164{
165    pub fn to_vec(&self) -> ManagedVec<M, T> {
166        let mut result = ManagedVec::new();
167        let serializer = ManagedSerializer::<M>::new();
168        for item in &self.raw_buffers {
169            result.push(serializer.top_decode_from_managed_buffer(&item));
170        }
171        result
172    }
173}
174
175impl<M, T> TopEncodeMulti for &MultiValueEncoded<M, T>
176where
177    M: ManagedTypeApi + ErrorApi,
178    T: TopEncodeMulti,
179{
180    fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
181    where
182        O: TopEncodeMultiOutput,
183        H: EncodeErrorHandler,
184    {
185        for elem in &self.raw_buffers {
186            elem.multi_encode_or_handle_err(output, h)?;
187        }
188        Ok(())
189    }
190}
191
192impl<M, T> TopEncodeMulti for MultiValueEncoded<M, T>
193where
194    M: ManagedTypeApi + ErrorApi,
195    T: TopEncodeMulti,
196{
197    fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
198    where
199        O: TopEncodeMultiOutput,
200        H: EncodeErrorHandler,
201    {
202        (&self).multi_encode_or_handle_err(output, h)
203    }
204}
205
206impl<M, T> TopDecodeMulti for MultiValueEncoded<M, T>
207where
208    M: ManagedTypeApi + ErrorApi,
209    T: TopDecodeMulti,
210{
211    fn multi_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
212    where
213        I: TopDecodeMultiInput,
214        H: DecodeErrorHandler,
215    {
216        let mut raw_buffers = ManagedVec::new();
217        while input.has_next() {
218            raw_buffers.push(input.next_value(h)?);
219        }
220        Ok(Self {
221            raw_buffers,
222            _phantom: PhantomData,
223        })
224    }
225}
226
227impl<M, T> TypeAbiFrom<Self> for MultiValueEncoded<M, T>
228where
229    M: ManagedTypeApi,
230    T: TypeAbi,
231{
232}
233
234impl<M, T> TypeAbiFrom<&Self> for MultiValueEncoded<M, T>
235where
236    M: ManagedTypeApi,
237    T: TypeAbi,
238{
239}
240
241impl<M, T> TypeAbi for MultiValueEncoded<M, T>
242where
243    M: ManagedTypeApi,
244    T: TypeAbi,
245{
246    type Unmanaged = MultiValueVec<T::Unmanaged>;
247
248    fn type_name() -> TypeName {
249        crate::abi::type_name_variadic::<T>()
250    }
251
252    fn type_name_rust() -> TypeName {
253        crate::abi::type_name_multi_value_encoded::<T>()
254    }
255
256    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
257        T::provide_type_descriptions(accumulator);
258    }
259
260    fn is_variadic() -> bool {
261        true
262    }
263}
264
265impl<M, T, U> TypeAbiFrom<MultiValueVec<T>> for MultiValueEncoded<M, U>
266where
267    M: ManagedTypeApi + ErrorApi,
268    T: TopEncodeMulti,
269    U: TypeAbiFrom<T>,
270{
271}
272
273impl<M, T, U> TypeAbiFrom<MultiValueEncoded<M, T>> for MultiValueVec<U>
274where
275    M: ManagedTypeApi + ErrorApi,
276    T: TopEncodeMulti,
277    U: TypeAbiFrom<T>,
278{
279}
280
281impl<M, V> FromIterator<V> for MultiValueEncoded<M, V>
282where
283    M: ManagedTypeApi,
284    V: TopEncodeMulti,
285{
286    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
287        let mut result: MultiValueEncoded<M, V> = MultiValueEncoded::new();
288        iter.into_iter().for_each(|f| result.push(f));
289        result
290    }
291}