1#[cfg(not(feature = "std"))]use alloc::vec::Vec;
10#[cfg(not(feature = "std"))]use alloc::string::String;
11
12#[cfg(feature = "std")] use std::cell::Cell;
13#[cfg(feature = "std")] use std::fmt;
14#[cfg(not(feature = "std"))] use core::cell::Cell;
15#[cfg(not(feature = "std"))] use core::fmt;
16use impls::decode_usize;
17use hexutil::to_hex;
18use {Decodable, DecoderError};
19
20#[derive(Copy, Clone, Debug)]
22struct OffsetCache {
23 index: usize,
24 offset: usize,
25}
26
27impl OffsetCache {
28 fn new(index: usize, offset: usize) -> OffsetCache {
29 OffsetCache {
30 index: index,
31 offset: offset,
32 }
33 }
34}
35
36#[derive(Debug)]
37pub enum Prototype {
39 Null,
41 Data(usize),
43 List(usize),
45}
46
47pub struct PayloadInfo {
49 pub header_len: usize,
51 pub value_len: usize,
53}
54
55fn calculate_payload_info(header_bytes: &[u8], len_of_len: usize) -> Result<PayloadInfo, DecoderError> {
56 let header_len = 1 + len_of_len;
57 match header_bytes.get(1) {
58 Some(&0) => return Err(DecoderError::RlpDataLenWithZeroPrefix),
59 None => return Err(DecoderError::RlpIsTooShort),
60 _ => (),
61 }
62 if header_bytes.len() < header_len { return Err(DecoderError::RlpIsTooShort); }
63 let value_len = decode_usize(&header_bytes[1..header_len])?;
64 Ok(PayloadInfo::new(header_len, value_len))
65}
66
67impl PayloadInfo {
68 fn new(header_len: usize, value_len: usize) -> PayloadInfo {
69 PayloadInfo {
70 header_len: header_len,
71 value_len: value_len,
72 }
73 }
74
75 pub fn total(&self) -> usize { self.header_len + self.value_len }
77
78 pub fn from(header_bytes: &[u8]) -> Result<PayloadInfo, DecoderError> {
80 match header_bytes.first().cloned() {
81 None => Err(DecoderError::RlpIsTooShort),
82 Some(0...0x7f) => Ok(PayloadInfo::new(0, 1)),
83 Some(l @ 0x80...0xb7) => Ok(PayloadInfo::new(1, l as usize - 0x80)),
84 Some(l @ 0xb8...0xbf) => {
85 let len_of_len = l as usize - 0xb7;
86 calculate_payload_info(header_bytes, len_of_len)
87 }
88 Some(l @ 0xc0...0xf7) => Ok(PayloadInfo::new(1, l as usize - 0xc0)),
89 Some(l @ 0xf8...0xff) => {
90 let len_of_len = l as usize - 0xf7;
91 calculate_payload_info(header_bytes, len_of_len)
92 },
93 _ => { unreachable!(); }
95 }
96 }
97}
98
99#[derive(Debug)]
106pub struct UntrustedRlp<'a> {
107 bytes: &'a [u8],
108 offset_cache: Cell<OffsetCache>,
109 count_cache: Cell<Option<usize>>,
110}
111
112impl<'a> Clone for UntrustedRlp<'a> {
113 fn clone(&self) -> UntrustedRlp<'a> {
114 UntrustedRlp {
115 bytes: self.bytes,
116 offset_cache: self.offset_cache.clone(),
117 count_cache: self.count_cache.clone(),
118 }
119 }
120}
121
122impl<'a> fmt::Display for UntrustedRlp<'a> {
123 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
124 match self.prototype() {
125 Ok(Prototype::Null) => write!(f, "null"),
126 Ok(Prototype::Data(_)) => write!(f, "\"{}\"", &to_hex(self.data().unwrap())),
127 Ok(Prototype::List(len)) => {
128 write!(f, "[")?;
129 for i in 0..len-1 {
130 write!(f, "{}, ", self.at(i).unwrap())?;
131 }
132 write!(f, "{}", self.at(len - 1).unwrap())?;
133 write!(f, "]")
134 },
135 Err(err) => write!(f, "{:?}", err)
136 }
137 }
138}
139
140impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
141 pub fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> {
142 UntrustedRlp {
143 bytes: bytes,
144 offset_cache: Cell::new(OffsetCache::new(usize::max_value(), 0)),
145 count_cache: Cell::new(None)
146 }
147 }
148
149 pub fn as_raw(&'view self) -> &'a [u8] {
150 self.bytes
151 }
152
153 pub fn prototype(&self) -> Result<Prototype, DecoderError> {
154 if self.is_data() {
156 Ok(Prototype::Data(self.size()))
157 } else if self.is_list() {
158 self.item_count().map(Prototype::List)
159 } else {
160 Ok(Prototype::Null)
161 }
162 }
163
164 pub fn payload_info(&self) -> Result<PayloadInfo, DecoderError> {
165 BasicDecoder::payload_info(self.bytes)
166 }
167
168 pub fn data(&'view self) -> Result<&'a [u8], DecoderError> {
169 let pi = BasicDecoder::payload_info(self.bytes)?;
170 Ok(&self.bytes[pi.header_len..(pi.header_len + pi.value_len)])
171 }
172
173 pub fn item_count(&self) -> Result<usize, DecoderError> {
174 match self.is_list() {
175 true => match self.count_cache.get() {
176 Some(c) => Ok(c),
177 None => {
178 let c = self.iter().count();
179 self.count_cache.set(Some(c));
180 Ok(c)
181 }
182 },
183 false => Err(DecoderError::RlpExpectedToBeList),
184 }
185 }
186
187 pub fn size(&self) -> usize {
188 match self.is_data() {
189 true => BasicDecoder::payload_info(self.bytes).map(|b| b.value_len).unwrap_or(0),
191 false => 0
192 }
193 }
194
195 pub fn at(&'view self, index: usize) -> Result<UntrustedRlp<'a>, DecoderError> {
196 if !self.is_list() {
197 return Err(DecoderError::RlpExpectedToBeList);
198 }
199
200 let c = self.offset_cache.get();
203 let (mut bytes, to_skip) = match c.index <= index {
204 true => (UntrustedRlp::consume(self.bytes, c.offset)?, index - c.index),
205 false => (self.consume_list_payload()?, index),
206 };
207
208 bytes = UntrustedRlp::consume_items(bytes, to_skip)?;
210
211 self.offset_cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
213
214 let found = BasicDecoder::payload_info(bytes)?;
216 Ok(UntrustedRlp::new(&bytes[0..found.header_len + found.value_len]))
217 }
218
219 pub fn is_null(&self) -> bool {
220 self.bytes.len() == 0
221 }
222
223 pub fn is_empty(&self) -> bool {
224 !self.is_null() && (self.bytes[0] == 0xc0 || self.bytes[0] == 0x80)
225 }
226
227 pub fn is_list(&self) -> bool {
228 !self.is_null() && self.bytes[0] >= 0xc0
229 }
230
231 pub fn is_data(&self) -> bool {
232 !self.is_null() && self.bytes[0] < 0xc0
233 }
234
235 pub fn is_int(&self) -> bool {
236 if self.is_null() {
237 return false;
238 }
239
240 match self.bytes[0] {
241 0...0x80 => true,
242 0x81...0xb7 => self.bytes[1] != 0,
243 b @ 0xb8...0xbf => self.bytes[1 + b as usize - 0xb7] != 0,
244 _ => false
245 }
246 }
247
248 pub fn iter(&'view self) -> UntrustedRlpIterator<'a, 'view> {
249 self.into_iter()
250 }
251
252 pub fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
253 T::decode(self)
254 }
255
256 pub fn as_list<T>(&self) -> Result<Vec<T>, DecoderError> where T: Decodable {
257 self.iter().map(|rlp| rlp.as_val()).collect()
258 }
259
260 pub fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
261 self.at(index)?.as_val()
262 }
263
264 pub fn list_at<T>(&self, index: usize) -> Result<Vec<T>, DecoderError> where T: Decodable {
265 self.at(index)?.as_list()
266 }
267
268 pub fn decoder(&self) -> BasicDecoder {
269 BasicDecoder::new(self.clone())
270 }
271
272 fn consume_list_payload(&self) -> Result<&'a [u8], DecoderError> {
274 let item = BasicDecoder::payload_info(self.bytes)?;
275 let bytes = UntrustedRlp::consume(self.bytes, item.header_len)?;
276 Ok(bytes)
277 }
278
279 fn consume_items(bytes: &'a [u8], items: usize) -> Result<&'a [u8], DecoderError> {
281 let mut result = bytes;
282 for _ in 0..items {
283 let i = BasicDecoder::payload_info(result)?;
284 result = UntrustedRlp::consume(result, (i.header_len + i.value_len))?;
285 }
286 Ok(result)
287 }
288
289
290 fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> {
292 match bytes.len() >= len {
293 true => Ok(&bytes[len..]),
294 false => Err(DecoderError::RlpIsTooShort),
295 }
296 }
297}
298
299pub struct UntrustedRlpIterator<'a, 'view> where 'a: 'view {
301 rlp: &'view UntrustedRlp<'a>,
302 index: usize,
303}
304
305impl<'a, 'view> IntoIterator for &'view UntrustedRlp<'a> where 'a: 'view {
306 type Item = UntrustedRlp<'a>;
307 type IntoIter = UntrustedRlpIterator<'a, 'view>;
308
309 fn into_iter(self) -> Self::IntoIter {
310 UntrustedRlpIterator {
311 rlp: self,
312 index: 0,
313 }
314 }
315}
316
317impl<'a, 'view> Iterator for UntrustedRlpIterator<'a, 'view> {
318 type Item = UntrustedRlp<'a>;
319
320 fn next(&mut self) -> Option<UntrustedRlp<'a>> {
321 let index = self.index;
322 let result = self.rlp.at(index).ok();
323 self.index += 1;
324 result
325 }
326}
327
328pub struct BasicDecoder<'a> {
329 rlp: UntrustedRlp<'a>
330}
331
332impl<'a> BasicDecoder<'a> {
333 pub fn new(rlp: UntrustedRlp<'a>) -> BasicDecoder<'a> {
334 BasicDecoder {
335 rlp: rlp
336 }
337 }
338
339 fn payload_info(bytes: &[u8]) -> Result<PayloadInfo, DecoderError> {
341 let item = PayloadInfo::from(bytes)?;
342 match item.header_len.checked_add(item.value_len) {
343 Some(x) if x <= bytes.len() => Ok(item),
344 _ => Err(DecoderError::RlpIsTooShort),
345 }
346 }
347
348 pub fn decode_value<T, F>(&self, f: F) -> Result<T, DecoderError>
349 where F: Fn(&[u8]) -> Result<T, DecoderError> {
350
351 let bytes = self.rlp.as_raw();
352
353 match bytes.first().cloned() {
354 None => Err(DecoderError::RlpIsTooShort),
356 Some(l @ 0...0x7f) => Ok(f(&[l])?),
358 Some(l @ 0x80...0xb7) => {
360 let last_index_of = 1 + l as usize - 0x80;
361 if bytes.len() < last_index_of {
362 return Err(DecoderError::RlpInconsistentLengthAndData);
363 }
364 let d = &bytes[1..last_index_of];
365 if l == 0x81 && d[0] < 0x80 {
366 return Err(DecoderError::RlpInvalidIndirection);
367 }
368 Ok(f(d)?)
369 },
370 Some(l @ 0xb8...0xbf) => {
372 let len_of_len = l as usize - 0xb7;
373 let begin_of_value = 1 as usize + len_of_len;
374 if bytes.len() < begin_of_value {
375 return Err(DecoderError::RlpInconsistentLengthAndData);
376 }
377 let len = decode_usize(&bytes[1..begin_of_value])?;
378
379 let last_index_of_value = begin_of_value + len;
380 if bytes.len() < last_index_of_value {
381 return Err(DecoderError::RlpInconsistentLengthAndData);
382 }
383 Ok(f(&bytes[begin_of_value..last_index_of_value])?)
384 }
385 _ => Err(DecoderError::RlpExpectedToBeData)
387 }
388 }
389}
390
391#[cfg(test)]
392mod tests {
393 use UntrustedRlp;
394 use hexutil::read_hex;
395
396 #[test]
397 fn test_rlp_display() {
398 let data = read_hex("f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap();
399 let rlp = UntrustedRlp::new(&data);
400 assert_eq!(format!("{}", rlp), "[\"0x05\", \"0x010efbef67941f79b2\", \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\", \"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\"]");
401 }
402}