esvm_rlp/
stream.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
9use std::borrow::Borrow;
10use byteorder::{ByteOrder, BigEndian};
11use elastic_array::{ElasticArray16, ElasticArray1024};
12use traits::Encodable;
13
14#[derive(Debug, Copy, Clone)]
15struct ListInfo {
16	position: usize,
17	current: usize,
18	max: Option<usize>,
19}
20
21impl ListInfo {
22	fn new(position: usize, max: Option<usize>) -> ListInfo {
23		ListInfo {
24			position: position,
25			current: 0,
26			max: max,
27		}
28	}
29}
30
31/// Appendable rlp encoder.
32pub struct RlpStream {
33	unfinished_lists: ElasticArray16<ListInfo>,
34	buffer: ElasticArray1024<u8>,
35	finished_list: bool,
36}
37
38impl Default for RlpStream {
39	fn default() -> Self {
40		RlpStream::new()
41	}
42}
43
44impl RlpStream {
45	/// Initializes instance of empty `Stream`.
46	pub fn new() -> Self {
47		RlpStream {
48			unfinished_lists: ElasticArray16::new(),
49			buffer: ElasticArray1024::new(),
50			finished_list: false,
51		}
52	}
53
54	/// Initializes the `Stream` as a list.
55	pub fn new_list(len: usize) -> Self {
56		let mut stream = RlpStream::new();
57		stream.begin_list(len);
58		stream
59	}
60
61	/// Appends value to the end of stream, chainable.
62	///
63	/// ```rust
64	/// extern crate rlp;
65	/// use rlp::*;
66	///
67	/// fn main () {
68	/// 	let mut stream = RlpStream::new_list(2);
69	/// 	stream.append(&"cat").append(&"dog");
70	/// 	let out = stream.out();
71	/// 	assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']);
72	/// }
73	/// ```
74	pub fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable {
75		self.finished_list = false;
76		value.rlp_append(self);
77		if !self.finished_list {
78			self.note_appended(1);
79		}
80		self
81	}
82
83	/// Appends list of values to the end of stream, chainable.
84	pub fn append_list<'a, E, K>(&'a mut self, values: &[K]) -> &'a mut Self where E: Encodable, K: Borrow<E> {
85		self.begin_list(values.len());
86		for value in values {
87			self.append(value.borrow());
88		}
89		self
90	}
91
92	/// Appends value to the end of stream, but do not count it as an appended item.
93	/// It's useful for wrapper types
94	pub fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable {
95		value.rlp_append(self);
96		self
97	}
98
99	/// Declare appending the list of given size, chainable.
100	///
101	/// ```rust
102	/// extern crate rlp;
103	/// use rlp::*;
104	///
105	/// fn main () {
106	/// 	let mut stream = RlpStream::new_list(2);
107	/// 	stream.begin_list(2).append(&"cat").append(&"dog");
108	/// 	stream.append(&"");
109	/// 	let out = stream.out();
110	/// 	assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]);
111	/// }
112	/// ```
113	pub fn begin_list(&mut self, len: usize) -> &mut RlpStream {
114		self.finished_list = false;
115		match len {
116			0 => {
117				// we may finish, if the appended list len is equal 0
118				self.buffer.push(0xc0u8);
119				self.note_appended(1);
120				self.finished_list = true;
121			},
122			_ => {
123				// payload is longer than 1 byte only for lists > 55 bytes
124				// by pushing always this 1 byte we may avoid unnecessary shift of data
125				self.buffer.push(0);
126
127				let position = self.buffer.len();
128				self.unfinished_lists.push(ListInfo::new(position, Some(len)));
129			},
130		}
131
132		// return chainable self
133		self
134	}
135
136
137	/// Declare appending the list of unknown size, chainable.
138	pub fn begin_unbounded_list(&mut self) -> &mut RlpStream {
139		self.finished_list = false;
140		// payload is longer than 1 byte only for lists > 55 bytes
141		// by pushing always this 1 byte we may avoid unnecessary shift of data
142		self.buffer.push(0);
143		let position = self.buffer.len();
144		self.unfinished_lists.push(ListInfo::new(position, None));
145		// return chainable self
146		self
147	}
148
149	/// Apends null to the end of stream, chainable.
150	///
151	/// ```rust
152	/// extern crate rlp;
153	/// use rlp::*;
154	///
155	/// fn main () {
156	/// 	let mut stream = RlpStream::new_list(2);
157	/// 	stream.append_empty_data().append_empty_data();
158	/// 	let out = stream.out();
159	/// 	assert_eq!(out, vec![0xc2, 0x80, 0x80]);
160	/// }
161	/// ```
162	pub fn append_empty_data(&mut self) -> &mut RlpStream {
163		// self push raw item
164		self.buffer.push(0x80);
165
166		// try to finish and prepend the length
167		self.note_appended(1);
168
169		// return chainable self
170		self
171	}
172
173	/// Appends raw (pre-serialised) RLP data. Use with caution. Chainable.
174	pub fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream {
175		// push raw items
176		self.buffer.append_slice(bytes);
177
178		// try to finish and prepend the length
179		self.note_appended(item_count);
180
181		// return chainable self
182		self
183	}
184
185	/// Appends raw (pre-serialised) RLP data. Checks for size oveflow.
186	pub fn append_raw_checked<'a>(&'a mut self, bytes: &[u8], item_count: usize, max_size: usize) -> bool {
187		if self.estimate_size(bytes.len()) > max_size {
188			return false;
189		}
190		self.append_raw(bytes, item_count);
191		true
192	}
193
194	/// Calculate total RLP size for appended payload.
195	pub fn estimate_size<'a>(&'a self, add: usize) -> usize {
196		let total_size = self.buffer.len() + add;
197		let mut base_size = total_size;
198		for list in &self.unfinished_lists[..] {
199			let len = total_size - list.position;
200			if len > 55 {
201				let leading_empty_bytes = (len as u64).leading_zeros() as usize / 8;
202				let size_bytes = 8 - leading_empty_bytes;
203				base_size += size_bytes;
204			}
205		}
206		base_size
207	}
208
209
210	/// Returns current RLP size in bytes for the data pushed into the list.
211	pub fn len<'a>(&'a self) -> usize {
212		self.estimate_size(0)
213	}
214
215	/// Clear the output stream so far.
216	///
217	/// ```rust
218	/// extern crate rlp;
219	/// use rlp::*;
220	///
221	/// fn main () {
222	/// 	let mut stream = RlpStream::new_list(3);
223	/// 	stream.append(&"cat");
224	/// 	stream.clear();
225	/// 	stream.append(&"dog");
226	/// 	let out = stream.out();
227	/// 	assert_eq!(out, vec![0x83, b'd', b'o', b'g']);
228	/// }
229	pub fn clear(&mut self) {
230		// clear bytes
231		self.buffer.clear();
232
233		// clear lists
234		self.unfinished_lists.clear();
235	}
236
237	/// Returns true if stream doesnt expect any more items.
238	///
239	/// ```rust
240	/// extern crate rlp;
241	/// use rlp::*;
242	///
243	/// fn main () {
244	/// 	let mut stream = RlpStream::new_list(2);
245	/// 	stream.append(&"cat");
246	/// 	assert_eq!(stream.is_finished(), false);
247	/// 	stream.append(&"dog");
248	/// 	assert_eq!(stream.is_finished(), true);
249	/// 	let out = stream.out();
250	/// 	assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']);
251	/// }
252	pub fn is_finished(&self) -> bool {
253		self.unfinished_lists.len() == 0
254	}
255
256	/// Get raw encoded bytes
257	pub fn as_raw(&self) -> &[u8] {
258		//&self.encoder.bytes
259		&self.buffer
260	}
261
262	/// Streams out encoded bytes.
263	///
264	/// panic! if stream is not finished.
265	pub fn out(self) -> Vec<u8> {
266		match self.is_finished() {
267			//true => self.encoder.out().to_vec(),
268			true => self.buffer.to_vec(),
269			false => panic!()
270		}
271	}
272
273	/// Try to finish lists
274	fn note_appended(&mut self, inserted_items: usize) -> () {
275		if self.unfinished_lists.len() == 0 {
276			return;
277		}
278
279		let back = self.unfinished_lists.len() - 1;
280		let should_finish = match self.unfinished_lists.get_mut(back) {
281			None => false,
282			Some(ref mut x) => {
283				x.current += inserted_items;
284				match x.max {
285					Some(ref max) if x.current > *max => panic!("You cannot append more items then you expect!"),
286					Some(ref max) => x.current == *max,
287					_ => false,
288				}
289			}
290		};
291
292		if should_finish {
293			let x = self.unfinished_lists.pop().unwrap();
294			let len = self.buffer.len() - x.position;
295			self.encoder().insert_list_payload(len, x.position);
296			self.note_appended(1);
297		}
298		self.finished_list = should_finish;
299	}
300
301	pub fn encoder(&mut self) -> BasicEncoder {
302		BasicEncoder::new(self)
303	}
304
305	/// Drain the object and return the underlying ElasticArray.
306	pub fn drain(self) -> ElasticArray1024<u8> {
307		match self.is_finished() {
308			true => self.buffer,
309			false => panic!()
310		}
311	}
312
313	/// Finalize current ubnbound list. Panics if no unbounded list has been opened.
314	pub fn complete_unbounded_list(&mut self) {
315		let list = self.unfinished_lists.pop().expect("No open list.");
316		if list.max.is_some() {
317			panic!("List type mismatch.");
318		}
319		let len = self.buffer.len() - list.position;
320		self.encoder().insert_list_payload(len, list.position);
321		self.note_appended(1);
322	}
323}
324
325pub struct BasicEncoder<'a> {
326	buffer: &'a mut ElasticArray1024<u8>,
327}
328
329impl<'a> BasicEncoder<'a> {
330	fn new(stream: &'a mut RlpStream) -> Self {
331		BasicEncoder {
332			buffer: &mut stream.buffer
333		}
334	}
335
336	fn insert_size(&mut self, size: usize, position: usize) -> u8 {
337		let size = size as u32;
338		let leading_empty_bytes = size.leading_zeros() as usize / 8;
339		let size_bytes = 4 - leading_empty_bytes as u8;
340		let mut buffer = [0u8; 4];
341		BigEndian::write_u32(&mut buffer, size);
342		self.buffer.insert_slice(position, &buffer[leading_empty_bytes..]);
343		size_bytes as u8
344	}
345
346	/// Inserts list prefix at given position
347	fn insert_list_payload(&mut self, len: usize, pos: usize) {
348		// 1 byte was already reserved for payload earlier
349		match len {
350			0...55 => {
351				self.buffer[pos - 1] = 0xc0u8 + len as u8;
352			},
353			_ => {
354				let inserted_bytes = self.insert_size(len, pos);
355				self.buffer[pos - 1] = 0xf7u8 + inserted_bytes;
356			}
357		};
358	}
359
360	/// Pushes encoded value to the end of buffer
361	pub fn encode_value(&mut self, value: &[u8]) {
362		match value.len() {
363			// just 0
364			0 => self.buffer.push(0x80u8),
365			// byte is its own encoding if < 0x80
366			1 if value[0] < 0x80 => self.buffer.push(value[0]),
367			// (prefix + length), followed by the string
368			len @ 1 ... 55 => {
369				self.buffer.push(0x80u8 + len as u8);
370				self.buffer.append_slice(value);
371			}
372			// (prefix + length of length), followed by the length, followd by the string
373			len => {
374				self.buffer.push(0);
375				let position = self.buffer.len();
376				let inserted_bytes = self.insert_size(len, position);
377				self.buffer[position - 1] = 0xb7 + inserted_bytes;
378				self.buffer.append_slice(value);
379			}
380		}
381	}
382}