1use super::{ABIDecodable, ABIDecodeError, ABIVariable};
6use cfx_bytes::Bytes;
7use cfx_types::U256;
8use std::{collections::LinkedList, slice::Iter};
9
10pub struct LinkedBytes {
11 length: usize,
12 data: LinkedList<Vec<u8>>,
13}
14
15pub fn padded_big_endian(length: usize) -> Vec<u8> {
16 let mut bytes = [0u8; 32];
17 U256::from(length).to_big_endian(&mut bytes);
18 bytes.to_vec()
19}
20
21impl LinkedBytes {
22 pub fn new() -> Self {
23 Self {
24 length: 0,
25 data: LinkedList::new(),
26 }
27 }
28
29 pub fn from_bytes(bytes: Vec<u8>) -> Self {
30 let mut answer = Self::new();
31 answer.length = bytes.len();
32 answer.data.push_back(bytes);
33 answer
34 }
35
36 pub fn append(&mut self, other: &mut Self) {
37 self.length += other.length;
38 self.data.append(&mut other.data);
39 other.length = 0;
40 }
41
42 pub fn to_vec(&self) -> Vec<u8> {
43 let mut answer = Vec::new();
44 for slice in &self.data {
45 answer.extend_from_slice(&slice)
46 }
47 answer
48 }
49
50 pub fn len(&self) -> usize { self.length }
51}
52
53pub fn read_abi_list<T: ABIVariable>(
54 data: &[u8], pointer: &mut Iter<u8>,
55) -> Result<T, ABIDecodeError> {
56 let res = if let Some(len) = T::STATIC_LENGTH {
57 pull_slice(pointer, len, "Incomplete static input parameter")?
58 } else {
59 let location = U256::from_big_endian(pull_slice(
60 pointer,
61 32,
62 "Incomplete location for dynamic input parameter",
63 )?);
64 abi_require(
65 location < U256::from(data.len()),
66 "Location out of bounds",
67 )?;
68 let loc = location.as_u64() as usize;
69 &data[loc..]
70 };
71 T::from_abi(res)
72}
73
74pub struct ABIListWriter {
75 heads_length: usize,
76 heads: LinkedBytes,
77 tails: LinkedBytes,
78}
79
80impl ABIListWriter {
81 pub fn with_heads_length(heads_length: usize) -> Self {
82 Self {
83 heads_length,
84 heads: LinkedBytes::new(),
85 tails: LinkedBytes::new(),
86 }
87 }
88
89 pub fn write_down<T: ABIVariable>(&mut self, input: &T) {
90 let mut encoded = input.to_abi();
91 if let Some(len) = T::STATIC_LENGTH {
92 assert_eq!(encoded.len(), len);
93 self.heads.append(&mut encoded);
94 } else {
95 let mut location = LinkedBytes::from_bytes(padded_big_endian(
96 self.tails.len() + self.heads_length,
97 ));
98 self.heads.append(&mut location);
99 self.tails.append(&mut encoded);
100 }
101 }
102
103 pub fn into_linked_bytes(mut self) -> LinkedBytes {
104 assert_eq!(self.heads.len(), self.heads_length);
105 self.heads.append(&mut self.tails);
106 self.heads
107 }
108}
109
110#[inline]
111pub fn abi_require(
112 claim: bool, desc: &'static str,
113) -> Result<(), ABIDecodeError> {
114 if !claim {
115 Err(ABIDecodeError(desc))
116 } else {
117 Ok(())
118 }
119}
120
121#[inline]
122pub fn pull_slice<'a>(
123 iter: &mut Iter<'a, u8>, n: usize, err_desc: &'static str,
124) -> Result<&'a [u8], ABIDecodeError> {
125 abi_require(iter.len() >= n, err_desc)?;
126
127 let slice = iter.as_slice();
128 let result = &slice[0..n];
129 *iter = slice[n..].iter();
130 Ok(result)
131}
132
133pub fn string_revert_reason_decode(output: &Bytes) -> String {
135 const MAX_LENGTH: usize = 50;
136 let decode_result = if output.len() < 4 {
137 Err(ABIDecodeError("Uncompleted Signature"))
138 } else {
139 let (sig, data) = output.split_at(4);
140 if sig != [8, 195, 121, 160] {
141 Err(ABIDecodeError("Unrecognized Signature"))
142 } else {
143 String::abi_decode(data)
144 }
145 };
146 match decode_result {
147 Ok(str) => {
148 if str.len() < MAX_LENGTH {
149 str
150 } else {
151 format!("{}...", str[..MAX_LENGTH].to_string())
152 }
153 }
154 Err(_) => "".to_string(),
155 }
156}
157
158#[cfg(test)]
159mod test {
160 use super::string_revert_reason_decode;
161 use rustc_hex::FromHex;
162
163 #[test]
164 fn test_decode_result() {
165 let input_hex = "08c379a0\
166 0000000000000000000000000000000000000000000000000000000000000020\
167 0000000000000000000000000000000000000000000000000000000000000018\
168 5468697320697320616e206572726f72206d6573736167650000000000000000\
169 ";
170 assert_eq!(
171 "This is an error message".to_string(),
172 string_revert_reason_decode(&input_hex.from_hex().unwrap())
173 );
174 }
175}