1#[cfg(not(feature = "std"))]
10use alloc::{string::String, vec::Vec};
11use core::{cell::Cell, fmt};
12
13use rustc_hex::ToHex;
14
15use crate::{error::DecoderError, impls::decode_usize, traits::Decodable};
16
17#[derive(Copy, Clone, Debug)]
19struct OffsetCache {
20 index: usize,
21 offset: usize,
22}
23
24impl OffsetCache {
25 const fn new(index: usize, offset: usize) -> OffsetCache {
26 OffsetCache { index, offset }
27 }
28}
29
30#[derive(Debug)]
31pub enum Prototype {
33 Null,
35 Data(usize),
37 List(usize),
39}
40
41#[derive(Debug)]
43pub struct PayloadInfo {
44 pub header_len: usize,
46 pub value_len: usize,
48}
49
50fn calculate_payload_info(header_bytes: &[u8], len_of_len: usize) -> Result<PayloadInfo, DecoderError> {
51 let header_len = 1 + len_of_len;
52 match header_bytes.get(1) {
53 Some(&0) => return Err(DecoderError::RlpDataLenWithZeroPrefix),
54 None => return Err(DecoderError::RlpIsTooShort),
55 _ => (),
56 }
57 if header_bytes.len() < header_len {
58 return Err(DecoderError::RlpIsTooShort)
59 }
60 let value_len = decode_usize(&header_bytes[1..header_len])?;
61 if value_len <= 55 {
62 return Err(DecoderError::RlpInvalidIndirection)
63 }
64 Ok(PayloadInfo::new(header_len, value_len))
65}
66
67impl PayloadInfo {
68 const fn new(header_len: usize, value_len: usize) -> PayloadInfo {
69 PayloadInfo { header_len, value_len }
70 }
71
72 pub fn total(&self) -> usize {
74 self.header_len + self.value_len
75 }
76
77 pub fn from(header_bytes: &[u8]) -> Result<PayloadInfo, DecoderError> {
79 let l = *header_bytes.first().ok_or_else(|| DecoderError::RlpIsTooShort)?;
80 if l <= 0x7f {
81 Ok(PayloadInfo::new(0, 1))
82 } else if l <= 0xb7 {
83 Ok(PayloadInfo::new(1, l as usize - 0x80))
84 } else if l <= 0xbf {
85 let len_of_len = l as usize - 0xb7;
86 calculate_payload_info(header_bytes, len_of_len)
87 } else if l <= 0xf7 {
88 Ok(PayloadInfo::new(1, l as usize - 0xc0))
89 } else {
90 let len_of_len = l as usize - 0xf7;
91 calculate_payload_info(header_bytes, len_of_len)
92 }
93 }
94}
95
96#[derive(Debug, Clone)]
103pub struct Rlp<'a> {
104 bytes: &'a [u8],
105 offset_cache: Cell<Option<OffsetCache>>,
106 count_cache: Cell<Option<usize>>,
107}
108
109impl<'a> fmt::Display for Rlp<'a> {
110 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
111 match self.prototype() {
112 Ok(Prototype::Null) => write!(f, "null"),
113 Ok(Prototype::Data(_)) => write!(f, "\"0x{}\"", self.data().unwrap().to_hex::<String>()),
114 Ok(Prototype::List(len)) => {
115 write!(f, "[")?;
116 for i in 0..len - 1 {
117 write!(f, "{}, ", self.at(i).unwrap())?;
118 }
119 write!(f, "{}", self.at(len - 1).unwrap())?;
120 write!(f, "]")
121 },
122 Err(err) => write!(f, "{:?}", err),
123 }
124 }
125}
126
127impl<'a> Rlp<'a> {
128 pub const fn new(bytes: &'a [u8]) -> Rlp<'a> {
129 Rlp { bytes, offset_cache: Cell::new(None), count_cache: Cell::new(None) }
130 }
131
132 pub fn as_raw<'view>(&'view self) -> &'a [u8]
133 where
134 'a: 'view,
135 {
136 self.bytes
137 }
138
139 pub fn prototype(&self) -> Result<Prototype, DecoderError> {
140 if self.is_data() {
142 Ok(Prototype::Data(self.size()))
143 } else if self.is_list() {
144 self.item_count().map(Prototype::List)
145 } else {
146 Ok(Prototype::Null)
147 }
148 }
149
150 pub fn payload_info(&self) -> Result<PayloadInfo, DecoderError> {
151 BasicDecoder::payload_info(self.bytes)
152 }
153
154 pub fn data<'view>(&'view self) -> Result<&'a [u8], DecoderError>
155 where
156 'a: 'view,
157 {
158 let pi = BasicDecoder::payload_info(self.bytes)?;
159 Ok(&self.bytes[pi.header_len..(pi.header_len + pi.value_len)])
160 }
161
162 pub fn item_count(&self) -> Result<usize, DecoderError> {
163 if self.is_list() {
164 match self.count_cache.get() {
165 Some(c) => Ok(c),
166 None => {
167 let c = self.iter().count();
168 self.count_cache.set(Some(c));
169 Ok(c)
170 },
171 }
172 } else {
173 Err(DecoderError::RlpExpectedToBeList)
174 }
175 }
176
177 pub fn size(&self) -> usize {
178 if self.is_data() {
179 BasicDecoder::payload_info(self.bytes).map(|b| b.value_len).unwrap_or(0)
181 } else {
182 0
183 }
184 }
185
186 pub fn at<'view>(&'view self, index: usize) -> Result<Rlp<'a>, DecoderError>
190 where
191 'a: 'view,
192 {
193 let (rlp, _offset) = self.at_with_offset(index)?;
194 Ok(rlp)
195 }
196
197 pub fn at_with_offset<'view>(&'view self, index: usize) -> Result<(Rlp<'a>, usize), DecoderError>
202 where
203 'a: 'view,
204 {
205 if !self.is_list() {
206 return Err(DecoderError::RlpExpectedToBeList)
207 }
208
209 let cache = self.offset_cache.get();
212 let (bytes, indexes_to_skip, bytes_consumed) = match cache {
213 Some(ref cache) if cache.index <= index =>
214 (Rlp::consume(self.bytes, cache.offset)?, index - cache.index, cache.offset),
215 _ => {
216 let (bytes, consumed) = self.consume_list_payload()?;
217 (bytes, index, consumed)
218 },
219 };
220
221 let (bytes, consumed) = Rlp::consume_items(bytes, indexes_to_skip)?;
223
224 let offset = bytes_consumed + consumed;
226 self.offset_cache.set(Some(OffsetCache::new(index, offset)));
227
228 let found = BasicDecoder::payload_info(bytes)?;
230 Ok((Rlp::new(&bytes[0..found.header_len + found.value_len]), offset))
231 }
232
233 pub fn is_null(&self) -> bool {
234 self.bytes.is_empty()
235 }
236
237 pub fn is_empty(&self) -> bool {
238 !self.is_null() && (self.bytes[0] == 0xc0 || self.bytes[0] == 0x80)
239 }
240
241 pub fn is_list(&self) -> bool {
242 !self.is_null() && self.bytes[0] >= 0xc0
243 }
244
245 pub fn is_data(&self) -> bool {
246 !self.is_null() && self.bytes[0] < 0xc0
247 }
248
249 pub fn is_int(&self) -> bool {
250 if self.is_null() {
251 return false
252 }
253
254 match self.bytes[0] {
255 0..=0x80 => true,
256 0x81..=0xb7 => self.bytes[1] != 0,
257 b @ 0xb8..=0xbf => {
258 let payload_idx = 1 + b as usize - 0xb7;
259 payload_idx < self.bytes.len() && self.bytes[payload_idx] != 0
260 },
261 _ => false,
262 }
263 }
264
265 pub fn iter<'view>(&'view self) -> RlpIterator<'a, 'view>
266 where
267 'a: 'view,
268 {
269 self.into_iter()
270 }
271
272 pub fn as_val<T>(&self) -> Result<T, DecoderError>
273 where
274 T: Decodable,
275 {
276 T::decode(self)
277 }
278
279 pub fn as_list<T>(&self) -> Result<Vec<T>, DecoderError>
280 where
281 T: Decodable,
282 {
283 self.iter().map(|rlp| rlp.as_val()).collect()
284 }
285
286 pub fn val_at<T>(&self, index: usize) -> Result<T, DecoderError>
287 where
288 T: Decodable,
289 {
290 self.at(index)?.as_val()
291 }
292
293 pub fn list_at<T>(&self, index: usize) -> Result<Vec<T>, DecoderError>
294 where
295 T: Decodable,
296 {
297 self.at(index)?.as_list()
298 }
299
300 pub fn decoder(&self) -> BasicDecoder {
301 BasicDecoder::new(self.bytes)
302 }
303
304 fn consume_list_payload(&self) -> Result<(&'a [u8], usize), DecoderError> {
306 let item = BasicDecoder::payload_info(self.bytes)?;
307 if self.bytes.len() < (item.header_len + item.value_len) {
308 return Err(DecoderError::RlpIsTooShort)
309 }
310 Ok((&self.bytes[item.header_len..item.header_len + item.value_len], item.header_len))
311 }
312
313 fn consume_items(bytes: &'a [u8], items: usize) -> Result<(&'a [u8], usize), DecoderError> {
315 let mut result = bytes;
316 let mut consumed = 0;
317 for _ in 0..items {
318 let i = BasicDecoder::payload_info(result)?;
319 let to_consume = i.header_len + i.value_len;
320 result = Rlp::consume(result, to_consume)?;
321 consumed += to_consume;
322 }
323 Ok((result, consumed))
324 }
325
326 fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> {
328 if bytes.len() >= len {
329 Ok(&bytes[len..])
330 } else {
331 Err(DecoderError::RlpIsTooShort)
332 }
333 }
334}
335
336pub struct RlpIterator<'a, 'view>
338where
339 'a: 'view,
340{
341 rlp: &'view Rlp<'a>,
342 index: usize,
343}
344
345impl<'a, 'view> IntoIterator for &'view Rlp<'a>
346where
347 'a: 'view,
348{
349 type Item = Rlp<'a>;
350 type IntoIter = RlpIterator<'a, 'view>;
351
352 fn into_iter(self) -> Self::IntoIter {
353 RlpIterator { rlp: self, index: 0 }
354 }
355}
356
357impl<'a, 'view> Iterator for RlpIterator<'a, 'view> {
358 type Item = Rlp<'a>;
359
360 fn next(&mut self) -> Option<Rlp<'a>> {
361 let index = self.index;
362 let result = self.rlp.at(index).ok();
363 self.index += 1;
364 result
365 }
366}
367
368impl<'a, 'view> ExactSizeIterator for RlpIterator<'a, 'view> {
369 fn len(&self) -> usize {
370 self.rlp.item_count().unwrap_or(0).saturating_sub(self.index)
371 }
372}
373
374pub struct BasicDecoder<'a> {
375 rlp: &'a [u8],
376}
377
378impl<'a> BasicDecoder<'a> {
379 pub const fn new(rlp: &'a [u8]) -> BasicDecoder<'a> {
380 BasicDecoder { rlp }
381 }
382
383 fn payload_info(bytes: &[u8]) -> Result<PayloadInfo, DecoderError> {
385 let item = PayloadInfo::from(bytes)?;
386 match item.header_len.checked_add(item.value_len) {
387 Some(x) if x <= bytes.len() => Ok(item),
388 _ => Err(DecoderError::RlpIsTooShort),
389 }
390 }
391
392 pub fn decode_value<T, F>(&self, f: F) -> Result<T, DecoderError>
393 where
394 F: Fn(&[u8]) -> Result<T, DecoderError>,
395 {
396 let bytes = self.rlp;
397
398 let l = *bytes.first().ok_or_else(|| DecoderError::RlpIsTooShort)?;
399
400 if l <= 0x7f {
401 Ok(f(&[l])?)
402 } else if l <= 0xb7 {
403 let last_index_of = 1 + l as usize - 0x80;
404 if bytes.len() < last_index_of {
405 return Err(DecoderError::RlpInconsistentLengthAndData)
406 }
407 let d = &bytes[1..last_index_of];
408 if l == 0x81 && d[0] < 0x80 {
409 return Err(DecoderError::RlpInvalidIndirection)
410 }
411 Ok(f(d)?)
412 } else if l <= 0xbf {
413 let len_of_len = l as usize - 0xb7;
414 let begin_of_value = 1 as usize + len_of_len;
415 if bytes.len() < begin_of_value {
416 return Err(DecoderError::RlpInconsistentLengthAndData)
417 }
418 let len = decode_usize(&bytes[1..begin_of_value])?;
419
420 let last_index_of_value = begin_of_value.checked_add(len).ok_or(DecoderError::RlpInvalidLength)?;
421 if bytes.len() < last_index_of_value {
422 return Err(DecoderError::RlpInconsistentLengthAndData)
423 }
424 Ok(f(&bytes[begin_of_value..last_index_of_value])?)
425 } else {
426 Err(DecoderError::RlpExpectedToBeData)
427 }
428 }
429}