rlp/
untrusted_rlp.rs

1// Copyright 2015-2017 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#[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/// rlp offset
21#[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)]
37/// RLP prototype
38pub enum Prototype {
39	/// Empty
40	Null,
41	/// Value
42	Data(usize),
43	/// List
44	List(usize),
45}
46
47/// Stores basic information about item
48pub struct PayloadInfo {
49	/// Header length in bytes
50	pub header_len: usize,
51	/// Value length in bytes
52	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	/// Total size of the RLP.
76	pub fn total(&self) -> usize { self.header_len + self.value_len }
77
78	/// Create a new object from the given bytes RLP. The bytes
79	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			// we cant reach this place, but rust requires _ to be implemented
94			_ => { unreachable!(); }
95		}
96	}
97}
98
99/// Data-oriented view onto rlp-slice.
100///
101/// This is immutable structere. No operations change it.
102///
103/// Should be used in places where, error handling is required,
104/// eg. on input
105#[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		// optimize? && return appropriate errors
155		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			// TODO: No panic on malformed data, but ideally would Err on no PayloadInfo.
190			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		// move to cached position if its index is less or equal to
201		// current search index, otherwise move to beginning of list
202		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		// skip up to x items
209		bytes = UntrustedRlp::consume_items(bytes, to_skip)?;
210
211		// update the cache
212		self.offset_cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
213
214		// construct new rlp
215		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	/// consumes first found prefix
273	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	/// consumes fixed number of items
280	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	/// consumes slice prefix of length `len`
291	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
299/// Iterator over rlp-slice list elements.
300pub 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	/// Return first item info.
340	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			// RLP is too short.
355			None => Err(DecoderError::RlpIsTooShort),
356			// Single byte value.
357			Some(l @ 0...0x7f) => Ok(f(&[l])?),
358			// 0-55 bytes
359			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			// Longer than 55 bytes.
371			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			// We are reading value, not a list!
386			_ => 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}