multiversx_sc/io/
bytes_arg_loader.rs

1use core::marker::PhantomData;
2
3use crate::codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput};
4use alloc::{boxed::Box, vec::Vec};
5
6use crate::{
7    api::{ErrorApi, ManagedTypeApi},
8    types::heap::BoxedBytes,
9};
10
11/// Consumes a vector of `BoxedBytes` and deserializes from the vector one by one.
12pub struct BytesArgLoader<A>
13where
14    A: ManagedTypeApi,
15{
16    bytes_vec: Vec<BoxedBytes>,
17    next_index: usize,
18    _phantom: PhantomData<A>,
19}
20
21impl<A> BytesArgLoader<A>
22where
23    A: ManagedTypeApi,
24{
25    pub fn new(bytes_vec: Vec<BoxedBytes>) -> Self {
26        BytesArgLoader {
27            bytes_vec,
28            next_index: 0,
29            _phantom: PhantomData,
30        }
31    }
32}
33
34impl<A> TopDecodeMultiInput for BytesArgLoader<A>
35where
36    A: ManagedTypeApi + ErrorApi,
37{
38    type ValueInput = Box<[u8]>;
39
40    fn has_next(&self) -> bool {
41        self.next_index < self.bytes_vec.len()
42    }
43
44    fn next_value_input<H>(&mut self, h: H) -> Result<Self::ValueInput, H::HandledErr>
45    where
46        H: DecodeErrorHandler,
47    {
48        if self.has_next() {
49            // consume from the vector, get owned bytes
50            // no clone
51            // no vector resize
52            let boxed_bytes =
53                core::mem::replace(&mut self.bytes_vec[self.next_index], BoxedBytes::empty());
54            self.next_index += 1;
55            Ok(boxed_bytes.into_box())
56        } else {
57            Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS))
58        }
59    }
60
61    fn flush_ignore<H>(&mut self, _h: H) -> Result<(), H::HandledErr>
62    where
63        H: DecodeErrorHandler,
64    {
65        self.next_index = self.bytes_vec.len();
66        Ok(())
67    }
68}