solidity_abi/
array.rs

1// Copyright 2020 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use super::{
6    utils::{
7        padded_big_endian, pull_slice, read_abi_list, ABIListWriter,
8        LinkedBytes,
9    },
10    ABIDecodeError, ABIVariable,
11};
12use cfx_types::U256;
13use std::{convert::TryFrom, fmt::Debug};
14
15impl<T: ABIVariable> ABIVariable for Vec<T> {
16    const BASIC_TYPE: bool = false;
17    const STATIC_LENGTH: Option<usize> = None;
18
19    fn from_abi(data: &[u8]) -> Result<Self, ABIDecodeError> {
20        let pointer = &mut data.iter();
21
22        let expected_length = U256::from_big_endian(pull_slice(
23            pointer,
24            32,
25            "Incomplete length for dynamic input parameter",
26        )?);
27        let data_without_length = pointer.as_slice();
28        let mut i = U256::zero();
29        let mut results = Vec::new();
30        while i < expected_length {
31            results.push(read_abi_list::<T>(data_without_length, pointer)?);
32            i = i + 1;
33        }
34        Ok(results)
35    }
36
37    fn to_abi(&self) -> LinkedBytes {
38        let length = LinkedBytes::from_bytes(padded_big_endian(self.len()));
39        let mut recorder = ABIListWriter::with_heads_length(
40            T::STATIC_LENGTH.unwrap_or(32) * self.len(),
41        );
42
43        for item in self {
44            recorder.write_down(item);
45        }
46        let mut answer = length;
47        answer.append(&mut recorder.into_linked_bytes());
48        answer
49    }
50
51    fn to_packed_abi(&self) -> LinkedBytes {
52        let mut record = LinkedBytes::new();
53
54        for item in self {
55            record.append(&mut item.to_packed_abi())
56        }
57        record
58    }
59}
60
61impl<T: ABIVariable + Debug, const N: usize> ABIVariable for [T; N] {
62    const BASIC_TYPE: bool = false;
63    const STATIC_LENGTH: Option<usize> = if let Some(length) = T::STATIC_LENGTH
64    {
65        Some(length * N)
66    } else {
67        None
68    };
69
70    fn from_abi(data: &[u8]) -> Result<Self, ABIDecodeError> {
71        let pointer = &mut data.iter();
72
73        let data_without_length = pointer.as_slice();
74        let mut results = Vec::new();
75        for _ in 0..N {
76            results.push(read_abi_list::<T>(data_without_length, pointer)?);
77        }
78        let results =
79            <[T; N]>::try_from(results).expect("Vector length must correct");
80        Ok(results)
81    }
82
83    fn to_abi(&self) -> LinkedBytes {
84        let mut recorder = ABIListWriter::with_heads_length(
85            T::STATIC_LENGTH.unwrap_or(32) * N,
86        );
87
88        for item in self {
89            recorder.write_down(item);
90        }
91        recorder.into_linked_bytes()
92    }
93
94    fn to_packed_abi(&self) -> LinkedBytes {
95        let mut record = LinkedBytes::new();
96
97        for item in self {
98            record.append(&mut item.to_packed_abi())
99        }
100        record
101    }
102}