// Copyright 2015-2017 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see . use elastic_array::*; use ::{Stream, Encoder, Encodable}; use bytes::{ToBytes, VecLike}; use rlptraits::{ByteEncodable, RlpEncodable}; #[derive(Debug, Copy, Clone)] struct ListInfo { position: usize, current: usize, max: usize, } impl ListInfo { fn new(position: usize, max: usize) -> ListInfo { ListInfo { position: position, current: 0, max: max, } } } /// Appendable rlp encoder. pub struct RlpStream { unfinished_lists: ElasticArray16, encoder: BasicEncoder, finished_list: bool, } impl Default for RlpStream { fn default() -> Self { RlpStream::new() } } impl Stream for RlpStream { fn new() -> Self { RlpStream { unfinished_lists: ElasticArray16::new(), encoder: BasicEncoder::new(), finished_list: false, } } fn new_list(len: usize) -> Self { let mut stream = RlpStream::new(); stream.begin_list(len); stream } fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable { self.finished_list = false; value.rlp_append(self); if !self.finished_list { self.note_appended(1); } self } fn begin_list(&mut self, len: usize) -> &mut RlpStream { self.finished_list = false; match len { 0 => { // we may finish, if the appended list len is equal 0 self.encoder.bytes.push(0xc0u8); self.note_appended(1); self.finished_list = true; }, _ => { let position = self.encoder.bytes.len(); self.unfinished_lists.push(ListInfo::new(position, len)); }, } // return chainable self self } fn append_empty_data(&mut self) -> &mut RlpStream { // self push raw item self.encoder.bytes.push(0x80); // try to finish and prepend the length self.note_appended(1); // return chainable self self } fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream { // push raw items self.encoder.bytes.append_slice(bytes); // try to finish and prepend the length self.note_appended(item_count); // return chainable self self } fn clear(&mut self) { // clear bytes self.encoder.bytes.clear(); // clear lists self.unfinished_lists.clear(); } fn is_finished(&self) -> bool { self.unfinished_lists.len() == 0 } fn as_raw(&self) -> &[u8] { &self.encoder.bytes } fn out(self) -> Vec { match self.is_finished() { true => self.encoder.out().to_vec(), false => panic!() } } } impl RlpStream { /// Appends primitive value to the end of stream fn append_value(&mut self, object: &E) where E: ByteEncodable { // encode given value and add it at the end of the stream self.encoder.emit_value(object); } fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { self.finished_list = false; value.rlp_append(self); if !self.finished_list { self.note_appended(1); } self } /// Try to finish lists fn note_appended(&mut self, inserted_items: usize) -> () { if self.unfinished_lists.len() == 0 { return; } let back = self.unfinished_lists.len() - 1; let should_finish = match self.unfinished_lists.get_mut(back) { None => false, Some(ref mut x) => { x.current += inserted_items; if x.current > x.max { panic!("You cannot append more items then you expect!"); } x.current == x.max } }; if should_finish { let x = self.unfinished_lists.pop().unwrap(); let len = self.encoder.bytes.len() - x.position; self.encoder.insert_list_len_at_pos(len, x.position); self.note_appended(1); } self.finished_list = should_finish; } /// Drain the object and return the underlying ElasticArray. pub fn drain(self) -> ElasticArray1024 { match self.is_finished() { true => self.encoder.bytes, false => panic!() } } } struct BasicEncoder { bytes: ElasticArray1024, } impl Default for BasicEncoder { fn default() -> Self { BasicEncoder::new() } } impl BasicEncoder { fn new() -> Self { BasicEncoder { bytes: ElasticArray1024::new() } } /// inserts list prefix at given position /// TODO: optimise it further? fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> () { let mut res = ElasticArray16::new(); match len { 0...55 => res.push(0xc0u8 + len as u8), _ => { res.push(0xf7u8 + len.to_bytes_len() as u8); ToBytes::to_bytes(&len, &mut res); } }; self.bytes.insert_slice(pos, &res); } /// get encoded value fn out(self) -> ElasticArray1024 { self.bytes } } impl Encoder for BasicEncoder { fn emit_value(&mut self, value: &E) { match value.bytes_len() { // just 0 0 => self.bytes.push(0x80u8), // byte is its own encoding if < 0x80 1 => { value.to_bytes(&mut self.bytes); let len = self.bytes.len(); let last_byte = self.bytes[len - 1]; if last_byte >= 0x80 { self.bytes.push(last_byte); self.bytes[len - 1] = 0x81; } } // (prefix + length), followed by the string len @ 2 ... 55 => { self.bytes.push(0x80u8 + len as u8); value.to_bytes(&mut self.bytes); } // (prefix + length of length), followed by the length, followd by the string len => { self.bytes.push(0xb7 + len.to_bytes_len() as u8); ToBytes::to_bytes(&len, &mut self.bytes); value.to_bytes(&mut self.bytes); } } } fn emit_raw(&mut self, bytes: &[u8]) -> () { self.bytes.append_slice(bytes); } } impl ByteEncodable for T where T: ToBytes { fn to_bytes>(&self, out: &mut V) { ToBytes::to_bytes(self, out) } fn bytes_len(&self) -> usize { ToBytes::to_bytes_len(self) } } struct U8Slice<'a>(&'a [u8]); impl<'a> ByteEncodable for U8Slice<'a> { fn to_bytes>(&self, out: &mut V) { out.vec_extend(self.0) } fn bytes_len(&self) -> usize { self.0.len() } } impl<'a> Encodable for &'a[u8] { fn rlp_append(&self, s: &mut RlpStream) { s.append_value(&U8Slice(self)) } } impl Encodable for Vec { fn rlp_append(&self, s: &mut RlpStream) { s.append_value(&U8Slice(self)) } } impl Encodable for T where T: ByteEncodable { fn rlp_append(&self, s: &mut RlpStream) { s.append_value(self) } } struct EncodableU8 (u8); impl ByteEncodable for EncodableU8 { fn to_bytes>(&self, out: &mut V) { if self.0 != 0 { out.vec_push(self.0) } } fn bytes_len(&self) -> usize { match self.0 { 0 => 0, _ => 1 } } } impl RlpEncodable for u8 { fn rlp_append(&self, s: &mut RlpStream) { s.append_value(&EncodableU8(*self)) } } impl<'a, T> Encodable for &'a[T] where T: Encodable { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(self.len()); for el in self.iter() { s.append_internal(el); } } } impl Encodable for Vec where T: Encodable { fn rlp_append(&self, s: &mut RlpStream) { Encodable::rlp_append(&self.as_slice(), s); } } impl Encodable for Option where T: Encodable { fn rlp_append(&self, s: &mut RlpStream) { match *self { None => { s.begin_list(0); }, Some(ref x) => { s.begin_list(1); s.append_internal(x); } } } } impl RlpEncodable for T where T: Encodable { fn rlp_append(&self, s: &mut RlpStream) { Encodable::rlp_append(self, s) } }