1#[cfg(not(feature = "std"))] use alloc::string::String;
10#[cfg(not(feature = "std"))] use alloc::vec::Vec;
11
12#[cfg(feature = "std")] use std::borrow::Borrow;
13#[cfg(not(feature = "std"))] use core::borrow::Borrow;
14use byteorder::{ByteOrder, BigEndian};
15use elastic_array::{ElasticArray16, ElasticArray1024};
16use traits::Encodable;
17
18#[derive(Debug, Copy, Clone)]
19struct ListInfo {
20 position: usize,
21 current: usize,
22 max: Option<usize>,
23}
24
25impl ListInfo {
26 fn new(position: usize, max: Option<usize>) -> ListInfo {
27 ListInfo {
28 position: position,
29 current: 0,
30 max: max,
31 }
32 }
33}
34
35pub struct RlpStream {
37 unfinished_lists: ElasticArray16<ListInfo>,
38 buffer: ElasticArray1024<u8>,
39 finished_list: bool,
40}
41
42impl Default for RlpStream {
43 fn default() -> Self {
44 RlpStream::new()
45 }
46}
47
48impl RlpStream {
49 pub fn new() -> Self {
51 RlpStream {
52 unfinished_lists: ElasticArray16::new(),
53 buffer: ElasticArray1024::new(),
54 finished_list: false,
55 }
56 }
57
58 pub fn new_list(len: usize) -> Self {
60 let mut stream = RlpStream::new();
61 stream.begin_list(len);
62 stream
63 }
64
65 pub fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable {
79 self.finished_list = false;
80 value.rlp_append(self);
81 if !self.finished_list {
82 self.note_appended(1);
83 }
84 self
85 }
86
87 pub fn append_list<'a, E, K>(&'a mut self, values: &[K]) -> &'a mut Self where E: Encodable, K: Borrow<E> {
89 self.begin_list(values.len());
90 for value in values {
91 self.append(value.borrow());
92 }
93 self
94 }
95
96 pub fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable {
99 value.rlp_append(self);
100 self
101 }
102
103 pub fn begin_list(&mut self, len: usize) -> &mut RlpStream {
118 self.finished_list = false;
119 match len {
120 0 => {
121 self.buffer.push(0xc0u8);
123 self.note_appended(1);
124 self.finished_list = true;
125 },
126 _ => {
127 self.buffer.push(0);
130
131 let position = self.buffer.len();
132 self.unfinished_lists.push(ListInfo::new(position, Some(len)));
133 },
134 }
135
136 self
138 }
139
140
141 pub fn begin_unbounded_list(&mut self) -> &mut RlpStream {
143 self.finished_list = false;
144 self.buffer.push(0);
147 let position = self.buffer.len();
148 self.unfinished_lists.push(ListInfo::new(position, None));
149 self
151 }
152
153 pub fn append_empty_data(&mut self) -> &mut RlpStream {
167 self.buffer.push(0x80);
169
170 self.note_appended(1);
172
173 self
175 }
176
177 pub fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream {
179 self.buffer.append_slice(bytes);
181
182 self.note_appended(item_count);
184
185 self
187 }
188
189 pub fn append_raw_checked<'a>(&'a mut self, bytes: &[u8], item_count: usize, max_size: usize) -> bool {
191 if self.estimate_size(bytes.len()) > max_size {
192 return false;
193 }
194 self.append_raw(bytes, item_count);
195 true
196 }
197
198 pub fn estimate_size<'a>(&'a self, add: usize) -> usize {
200 let total_size = self.buffer.len() + add;
201 let mut base_size = total_size;
202 for list in &self.unfinished_lists[..] {
203 let len = total_size - list.position;
204 if len > 55 {
205 let leading_empty_bytes = (len as u64).leading_zeros() as usize / 8;
206 let size_bytes = 8 - leading_empty_bytes;
207 base_size += size_bytes;
208 }
209 }
210 base_size
211 }
212
213
214 pub fn len<'a>(&'a self) -> usize {
216 self.estimate_size(0)
217 }
218
219 pub fn clear(&mut self) {
234 self.buffer.clear();
236
237 self.unfinished_lists.clear();
239 }
240
241 pub fn is_finished(&self) -> bool {
257 self.unfinished_lists.len() == 0
258 }
259
260 pub fn as_raw(&self) -> &[u8] {
262 &self.buffer
264 }
265
266 pub fn out(self) -> Vec<u8> {
270 match self.is_finished() {
271 true => self.buffer.to_vec(),
273 false => panic!()
274 }
275 }
276
277 fn note_appended(&mut self, inserted_items: usize) -> () {
279 if self.unfinished_lists.len() == 0 {
280 return;
281 }
282
283 let back = self.unfinished_lists.len() - 1;
284 let should_finish = match self.unfinished_lists.get_mut(back) {
285 None => false,
286 Some(ref mut x) => {
287 x.current += inserted_items;
288 match x.max {
289 Some(ref max) if x.current > *max => panic!("You cannot append more items then you expect!"),
290 Some(ref max) => x.current == *max,
291 _ => false,
292 }
293 }
294 };
295
296 if should_finish {
297 let x = self.unfinished_lists.pop().unwrap();
298 let len = self.buffer.len() - x.position;
299 self.encoder().insert_list_payload(len, x.position);
300 self.note_appended(1);
301 }
302 self.finished_list = should_finish;
303 }
304
305 pub fn encoder(&mut self) -> BasicEncoder {
306 BasicEncoder::new(self)
307 }
308
309 pub fn drain(self) -> ElasticArray1024<u8> {
311 match self.is_finished() {
312 true => self.buffer,
313 false => panic!()
314 }
315 }
316
317 pub fn complete_unbounded_list(&mut self) {
319 let list = self.unfinished_lists.pop().expect("No open list.");
320 if list.max.is_some() {
321 panic!("List type mismatch.");
322 }
323 let len = self.buffer.len() - list.position;
324 self.encoder().insert_list_payload(len, list.position);
325 self.note_appended(1);
326 }
327}
328
329pub struct BasicEncoder<'a> {
330 buffer: &'a mut ElasticArray1024<u8>,
331}
332
333impl<'a> BasicEncoder<'a> {
334 fn new(stream: &'a mut RlpStream) -> Self {
335 BasicEncoder {
336 buffer: &mut stream.buffer
337 }
338 }
339
340 fn insert_size(&mut self, size: usize, position: usize) -> u8 {
341 let size = size as u32;
342 let leading_empty_bytes = size.leading_zeros() as usize / 8;
343 let size_bytes = 4 - leading_empty_bytes as u8;
344 let mut buffer = [0u8; 4];
345 BigEndian::write_u32(&mut buffer, size);
346 self.buffer.insert_slice(position, &buffer[leading_empty_bytes..]);
347 size_bytes as u8
348 }
349
350 fn insert_list_payload(&mut self, len: usize, pos: usize) {
352 match len {
354 0...55 => {
355 self.buffer[pos - 1] = 0xc0u8 + len as u8;
356 },
357 _ => {
358 let inserted_bytes = self.insert_size(len, pos);
359 self.buffer[pos - 1] = 0xf7u8 + inserted_bytes;
360 }
361 };
362 }
363
364 pub fn encode_value(&mut self, value: &[u8]) {
366 match value.len() {
367 0 => self.buffer.push(0x80u8),
369 1 if value[0] < 0x80 => self.buffer.push(value[0]),
371 len @ 1 ... 55 => {
373 self.buffer.push(0x80u8 + len as u8);
374 self.buffer.append_slice(value);
375 }
376 len => {
378 self.buffer.push(0);
379 let position = self.buffer.len();
380 let inserted_bytes = self.insert_size(len, position);
381 self.buffer[position - 1] = 0xb7 + inserted_bytes;
382 self.buffer.append_slice(value);
383 }
384 }
385 }
386}