commit
						5210f9e56d
					
				
							
								
								
									
										17
									
								
								src/block.rs
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/block.rs
									
									
									
									
									
								
							@ -45,14 +45,14 @@ impl Decodable for Block {
 | 
			
		||||
		if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
 | 
			
		||||
			return Err(DecoderError::RlpIsTooBig);	
 | 
			
		||||
		}
 | 
			
		||||
		let d = try!(decoder.as_list());
 | 
			
		||||
		if d.len() != 3 {
 | 
			
		||||
		let d = decoder.as_rlp();
 | 
			
		||||
		if d.item_count() != 3 {
 | 
			
		||||
			return Err(DecoderError::RlpIncorrectListLen);
 | 
			
		||||
		}
 | 
			
		||||
		Ok(Block {
 | 
			
		||||
			header: try!(Decodable::decode(&d[0])),
 | 
			
		||||
			transactions: try!(Decodable::decode(&d[1])),
 | 
			
		||||
			uncles: try!(Decodable::decode(&d[2])),
 | 
			
		||||
			header: try!(d.val_at(0)),
 | 
			
		||||
			transactions: try!(d.val_at(1)),
 | 
			
		||||
			uncles: try!(d.val_at(2)),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -245,11 +245,11 @@ impl<'x, 'y> OpenBlock<'x, 'y> {
 | 
			
		||||
	pub fn close(self) -> ClosedBlock<'x, 'y> {
 | 
			
		||||
		let mut s = self;
 | 
			
		||||
		s.engine.on_close_block(&mut s.block);
 | 
			
		||||
		s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|ref e| e.rlp_bytes()).collect());
 | 
			
		||||
		s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|ref e| e.rlp_bytes().to_vec()).collect());
 | 
			
		||||
		let uncle_bytes = s.block.base.uncles.iter().fold(RlpStream::new_list(s.block.base.uncles.len()), |mut s, u| {s.append(&u.rlp(Seal::With)); s} ).out();
 | 
			
		||||
		s.block.base.header.uncles_hash = uncle_bytes.sha3();
 | 
			
		||||
		s.block.base.header.state_root = s.block.state.root().clone();
 | 
			
		||||
		s.block.base.header.receipts_root = ordered_trie_root(s.block.receipts.iter().map(|ref r| r.rlp_bytes()).collect());
 | 
			
		||||
		s.block.base.header.receipts_root = ordered_trie_root(s.block.receipts.iter().map(|ref r| r.rlp_bytes().to_vec()).collect());
 | 
			
		||||
		s.block.base.header.log_bloom = s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b |= &r.log_bloom; b});
 | 
			
		||||
		s.block.base.header.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used);
 | 
			
		||||
		s.block.base.header.note_dirty();
 | 
			
		||||
@ -301,8 +301,7 @@ impl SealedBlock {
 | 
			
		||||
	pub fn rlp_bytes(&self) -> Bytes {
 | 
			
		||||
		let mut block_rlp = RlpStream::new_list(3);
 | 
			
		||||
		self.block.base.header.stream_rlp(&mut block_rlp, Seal::With);
 | 
			
		||||
		block_rlp.append_list(self.block.receipts.len());
 | 
			
		||||
		for t in &self.block.base.transactions { t.rlp_append(&mut block_rlp); }
 | 
			
		||||
		block_rlp.append(&self.block.base.transactions);
 | 
			
		||||
		block_rlp.append_raw(&self.uncle_bytes, 1);
 | 
			
		||||
		block_rlp.out()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@ impl Engine for Ethash {
 | 
			
		||||
	// Two fields - mix
 | 
			
		||||
	fn seal_fields(&self) -> usize { 2 }
 | 
			
		||||
	// Two empty data items in RLP.
 | 
			
		||||
	fn seal_rlp(&self) -> Bytes { encode(&H64::new()) }
 | 
			
		||||
	fn seal_rlp(&self) -> Bytes { encode(&H64::new()).to_vec() }
 | 
			
		||||
 | 
			
		||||
	/// Additional engine-specific information for the user/developer concerning `header`.
 | 
			
		||||
	fn extra_info(&self, _header: &Header) -> HashMap<String, String> { HashMap::new() }
 | 
			
		||||
 | 
			
		||||
@ -133,25 +133,24 @@ impl HeapSizeOf for BlockDetails {
 | 
			
		||||
 | 
			
		||||
impl Decodable for BlockDetails {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
 | 
			
		||||
		let d = try!(decoder.as_list());
 | 
			
		||||
		let d = decoder.as_rlp();
 | 
			
		||||
		let details = BlockDetails {
 | 
			
		||||
			number: try!(Decodable::decode(&d[0])),
 | 
			
		||||
			total_difficulty: try!(Decodable::decode(&d[1])),
 | 
			
		||||
			parent: try!(Decodable::decode(&d[2])),
 | 
			
		||||
			children: try!(Decodable::decode(&d[3]))
 | 
			
		||||
			number: try!(d.val_at(0)),
 | 
			
		||||
			total_difficulty: try!(d.val_at(1)),
 | 
			
		||||
			parent: try!(d.val_at(2)),
 | 
			
		||||
			children: try!(d.val_at(3)),
 | 
			
		||||
		};
 | 
			
		||||
		Ok(details)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encodable for BlockDetails {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_list(| e | {
 | 
			
		||||
			self.number.encode(e);
 | 
			
		||||
			self.total_difficulty.encode(e);
 | 
			
		||||
			self.parent.encode(e);
 | 
			
		||||
			self.children.encode(e);
 | 
			
		||||
		})
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.begin_list(4);
 | 
			
		||||
		s.append(&self.number);
 | 
			
		||||
		s.append(&self.total_difficulty);
 | 
			
		||||
		s.append(&self.parent);
 | 
			
		||||
		s.append(&self.children);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -185,8 +184,8 @@ impl Decodable for BlockLogBlooms {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encodable for BlockLogBlooms {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		self.blooms.encode(encoder);
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.append(&self.blooms);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -231,9 +230,9 @@ impl Decodable for BlocksBlooms {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encodable for BlocksBlooms {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		let blooms_ref: &[H2048] = &self.blooms;
 | 
			
		||||
		blooms_ref.encode(encoder);
 | 
			
		||||
		s.append(&blooms_ref);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -258,10 +257,10 @@ impl HeapSizeOf for TransactionAddress {
 | 
			
		||||
 | 
			
		||||
impl Decodable for TransactionAddress {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
 | 
			
		||||
		let d = try!(decoder.as_list());
 | 
			
		||||
		let d = decoder.as_rlp();
 | 
			
		||||
		let tx_address = TransactionAddress {
 | 
			
		||||
			block_hash: try!(Decodable::decode(&d[0])),
 | 
			
		||||
			index: try!(Decodable::decode(&d[1]))
 | 
			
		||||
			block_hash: try!(d.val_at(0)),
 | 
			
		||||
			index: try!(d.val_at(1)),
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		Ok(tx_address)
 | 
			
		||||
@ -269,10 +268,9 @@ impl Decodable for TransactionAddress {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encodable for TransactionAddress {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_list(| e | {
 | 
			
		||||
			self.block_hash.encode(e);
 | 
			
		||||
			self.index.encode(e);
 | 
			
		||||
		})
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.begin_list(2);
 | 
			
		||||
		s.append(&self.block_hash);
 | 
			
		||||
		s.append(&self.index);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -157,7 +157,7 @@ impl Header {
 | 
			
		||||
	// TODO: make these functions traity 
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	pub fn stream_rlp(&self, s: &mut RlpStream, with_seal: Seal) {
 | 
			
		||||
		s.append_list(13 + match with_seal { Seal::With => self.seal.len(), _ => 0 });
 | 
			
		||||
		s.begin_list(13 + match with_seal { Seal::With => self.seal.len(), _ => 0 });
 | 
			
		||||
		s.append(&self.parent_hash);
 | 
			
		||||
		s.append(&self.uncles_hash);
 | 
			
		||||
		s.append(&self.author);
 | 
			
		||||
@ -221,26 +221,8 @@ impl Decodable for Header {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encodable for Header {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_list(| e | {
 | 
			
		||||
			self.parent_hash.encode(e);
 | 
			
		||||
			self.uncles_hash.encode(e);
 | 
			
		||||
			self.author.encode(e);
 | 
			
		||||
			self.state_root.encode(e);
 | 
			
		||||
			self.transactions_root.encode(e);
 | 
			
		||||
			self.receipts_root.encode(e);
 | 
			
		||||
			self.log_bloom.encode(e);
 | 
			
		||||
			self.difficulty.encode(e);
 | 
			
		||||
			self.number.encode(e);
 | 
			
		||||
			self.gas_limit.encode(e);
 | 
			
		||||
			self.gas_used.encode(e);
 | 
			
		||||
			self.timestamp.encode(e);
 | 
			
		||||
			self.extra_data.encode(e);
 | 
			
		||||
 | 
			
		||||
			for b in &self.seal {
 | 
			
		||||
				e.emit_raw(&b);
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		self.stream_rlp(s, Seal::With);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,9 +12,9 @@ pub struct LogEntry {
 | 
			
		||||
	pub data: Bytes,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl RlpStandard for LogEntry {
 | 
			
		||||
impl Encodable for LogEntry {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.append_list(3);
 | 
			
		||||
		s.begin_list(3);
 | 
			
		||||
		s.append(&self.address);
 | 
			
		||||
		s.append(&self.topics);
 | 
			
		||||
		s.append(&self.data);
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ impl PodAccount {
 | 
			
		||||
		let mut stream = RlpStream::new_list(4);
 | 
			
		||||
		stream.append(&self.nonce);
 | 
			
		||||
		stream.append(&self.balance);
 | 
			
		||||
		stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), encode(&U256::from(v.as_slice())))).collect()));
 | 
			
		||||
		stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), encode(&U256::from(v.as_slice())).to_vec())).collect()));
 | 
			
		||||
		stream.append(&self.code.sha3());
 | 
			
		||||
		stream.out()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -27,17 +27,12 @@ impl Receipt {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl RlpStandard for Receipt {
 | 
			
		||||
impl Encodable for Receipt {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.append_list(4);
 | 
			
		||||
		s.begin_list(4);
 | 
			
		||||
		s.append(&self.state_root);
 | 
			
		||||
		s.append(&self.gas_used);
 | 
			
		||||
		s.append(&self.log_bloom);
 | 
			
		||||
		// TODO: make work:
 | 
			
		||||
		//s.append(&self.logs);
 | 
			
		||||
		s.append_list(self.logs.len());
 | 
			
		||||
		for l in &self.logs {
 | 
			
		||||
			l.rlp_append(s);
 | 
			
		||||
		}
 | 
			
		||||
		s.append(&self.logs);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/spec.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/spec.rs
									
									
									
									
									
								
							@ -20,14 +20,14 @@ pub fn gzip64res_to_json(source: &[u8]) -> Json {
 | 
			
		||||
// TODO: handle container types.
 | 
			
		||||
fn json_to_rlp(json: &Json) -> Bytes {
 | 
			
		||||
	match *json {
 | 
			
		||||
		Json::Boolean(o) => encode(&(if o {1u64} else {0})),
 | 
			
		||||
		Json::I64(o) => encode(&(o as u64)),
 | 
			
		||||
		Json::U64(o) => encode(&o),
 | 
			
		||||
		Json::Boolean(o) => encode(&(if o {1u64} else {0})).to_vec(),
 | 
			
		||||
		Json::I64(o) => encode(&(o as u64)).to_vec(),
 | 
			
		||||
		Json::U64(o) => encode(&o).to_vec(),
 | 
			
		||||
		Json::String(ref s) if s.len() >= 2 && &s[0..2] == "0x" && U256::from_str(&s[2..]).is_ok() => {
 | 
			
		||||
			encode(&U256::from_str(&s[2..]).unwrap())
 | 
			
		||||
			encode(&U256::from_str(&s[2..]).unwrap()).to_vec()
 | 
			
		||||
		},
 | 
			
		||||
		Json::String(ref s) => {
 | 
			
		||||
			encode(s)
 | 
			
		||||
			encode(s).to_vec()
 | 
			
		||||
		},
 | 
			
		||||
		_ => panic!()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -325,7 +325,6 @@ impl TestNet {
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn chain_two_peers() {
 | 
			
		||||
	::env_logger::init().ok();
 | 
			
		||||
	let mut net = TestNet::new(3);
 | 
			
		||||
	net.peer_mut(1).chain.add_blocks(1000, false);
 | 
			
		||||
	net.peer_mut(2).chain.add_blocks(1000, false);
 | 
			
		||||
@ -336,7 +335,6 @@ fn chain_two_peers() {
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn chain_status_after_sync() {
 | 
			
		||||
	::env_logger::init().ok();
 | 
			
		||||
	let mut net = TestNet::new(3);
 | 
			
		||||
	net.peer_mut(1).chain.add_blocks(1000, false);
 | 
			
		||||
	net.peer_mut(2).chain.add_blocks(1000, false);
 | 
			
		||||
@ -356,7 +354,6 @@ fn chain_takes_few_steps() {
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn chain_empty_blocks() {
 | 
			
		||||
	::env_logger::init().ok();
 | 
			
		||||
	let mut net = TestNet::new(3);
 | 
			
		||||
	for n in 0..200 {
 | 
			
		||||
		net.peer_mut(1).chain.add_blocks(5, n % 2 == 0);
 | 
			
		||||
@ -368,8 +365,7 @@ fn chain_empty_blocks() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn chain_forged() {
 | 
			
		||||
	::env_logger::init().ok();
 | 
			
		||||
fn chain_forked() {
 | 
			
		||||
	let mut net = TestNet::new(3);
 | 
			
		||||
	net.peer_mut(0).chain.add_blocks(300, false);
 | 
			
		||||
	net.peer_mut(1).chain.add_blocks(300, false);
 | 
			
		||||
 | 
			
		||||
@ -89,14 +89,11 @@ fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes {
 | 
			
		||||
pub fn create_test_block_with_data(header: &Header, transactions: &[&Transaction], uncles: &[Header]) -> Bytes {
 | 
			
		||||
	let mut rlp = RlpStream::new_list(3);
 | 
			
		||||
	rlp.append(header);
 | 
			
		||||
	rlp.append_list(transactions.len());
 | 
			
		||||
	rlp.begin_list(transactions.len());
 | 
			
		||||
	for t in transactions {
 | 
			
		||||
		rlp.append_raw(&t.rlp_bytes_opt(Seal::With), 1);
 | 
			
		||||
	}
 | 
			
		||||
	rlp.append_list(uncles.len());
 | 
			
		||||
	for h in uncles {
 | 
			
		||||
		rlp.append(h);
 | 
			
		||||
	}
 | 
			
		||||
	rlp.append(&uncles);
 | 
			
		||||
	rlp.out()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,7 @@ impl Transaction {
 | 
			
		||||
 | 
			
		||||
	/// Append object into RLP stream, optionally with or without the signature.
 | 
			
		||||
	pub fn rlp_append_opt(&self, s: &mut RlpStream, with_seal: Seal) {
 | 
			
		||||
		s.append_list(6 + match with_seal { Seal::With => 3, _ => 0 });
 | 
			
		||||
		s.begin_list(6 + match with_seal { Seal::With => 3, _ => 0 });
 | 
			
		||||
		s.append(&self.nonce);
 | 
			
		||||
		s.append(&self.gas_price);
 | 
			
		||||
		s.append(&self.gas);
 | 
			
		||||
@ -162,7 +162,7 @@ impl FromJson for Transaction {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl RlpStandard for Transaction {
 | 
			
		||||
impl Encodable for Transaction {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) { self.rlp_append_opt(s, Seal::With) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -267,20 +267,20 @@ impl Decodable for Action {
 | 
			
		||||
 | 
			
		||||
impl Decodable for Transaction {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
 | 
			
		||||
		let d = try!(decoder.as_list());
 | 
			
		||||
		if d.len() != 9 {
 | 
			
		||||
		let d = decoder.as_rlp();
 | 
			
		||||
		if d.item_count() != 9 {
 | 
			
		||||
			return Err(DecoderError::RlpIncorrectListLen);
 | 
			
		||||
		}
 | 
			
		||||
		Ok(Transaction {
 | 
			
		||||
			nonce: try!(Decodable::decode(&d[0])),
 | 
			
		||||
			gas_price: try!(Decodable::decode(&d[1])),
 | 
			
		||||
			gas: try!(Decodable::decode(&d[2])),
 | 
			
		||||
			action: try!(Decodable::decode(&d[3])),
 | 
			
		||||
			value: try!(Decodable::decode(&d[4])),
 | 
			
		||||
			data: try!(Decodable::decode(&d[5])),
 | 
			
		||||
			v: try!(u16::decode(&d[6])) as u8,
 | 
			
		||||
			r: try!(Decodable::decode(&d[7])),
 | 
			
		||||
			s: try!(Decodable::decode(&d[8])),
 | 
			
		||||
			nonce: try!(d.val_at(0)),
 | 
			
		||||
			gas_price: try!(d.val_at(1)),
 | 
			
		||||
			gas: try!(d.val_at(2)),
 | 
			
		||||
			action: try!(d.val_at(3)),
 | 
			
		||||
			value: try!(d.val_at(4)),
 | 
			
		||||
			data: try!(d.val_at(5)),
 | 
			
		||||
			v: try!(d.val_at(6)),
 | 
			
		||||
			r: try!(d.val_at(7)),
 | 
			
		||||
			s: try!(d.val_at(8)),
 | 
			
		||||
			hash: RefCell::new(None),
 | 
			
		||||
			sender: RefCell::new(None),
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
@ -11,39 +11,55 @@
 | 
			
		||||
//! 	let slice: &[u8] = arr.bytes();
 | 
			
		||||
//! }
 | 
			
		||||
//!
 | 
			
		||||
//! fn to_bytes() {
 | 
			
		||||
//! 	use util::bytes::ToBytes;
 | 
			
		||||
//!
 | 
			
		||||
//! 	let a: Vec<u8> = "hello_world".to_bytes();
 | 
			
		||||
//! 	let b: Vec<u8> = 400u32.to_bytes();
 | 
			
		||||
//! 	let c: Vec<u8> = 0xffffffffffffffffu64.to_bytes();
 | 
			
		||||
//! }
 | 
			
		||||
//!
 | 
			
		||||
//! fn from_bytes() {
 | 
			
		||||
//! 	use util::bytes::FromBytes;
 | 
			
		||||
//!
 | 
			
		||||
//! 	let a = String::from_bytes(&[b'd', b'o', b'g']);
 | 
			
		||||
//! 	let b = u16::from_bytes(&[0xfa]);
 | 
			
		||||
//! 	let c = u64::from_bytes(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
 | 
			
		||||
//! }
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() {
 | 
			
		||||
//! 	bytes_convertable();
 | 
			
		||||
//! 	to_bytes();
 | 
			
		||||
//! 	from_bytes();
 | 
			
		||||
//! }
 | 
			
		||||
//! ```
 | 
			
		||||
 | 
			
		||||
use std::mem;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::slice;
 | 
			
		||||
use std::cmp::Ordering;
 | 
			
		||||
use std::error::Error as StdError;
 | 
			
		||||
use std::ops::{Deref, DerefMut};
 | 
			
		||||
use uint::{Uint, U128, U256};
 | 
			
		||||
use hash::FixedHash;
 | 
			
		||||
use elastic_array::*;
 | 
			
		||||
 | 
			
		||||
/// TODO [Gav Wood] Please document me
 | 
			
		||||
/// Vector like object
 | 
			
		||||
pub trait VecLike<T> {
 | 
			
		||||
	/// Add an element to the collection
 | 
			
		||||
    fn vec_push(&mut self, value: T);
 | 
			
		||||
 | 
			
		||||
	/// Add a slice to the collection
 | 
			
		||||
    fn vec_extend(&mut self, slice: &[T]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> VecLike<T> for Vec<T> where T: Copy {
 | 
			
		||||
	fn vec_push(&mut self, value: T) {
 | 
			
		||||
		Vec::<T>::push(self, value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn vec_extend(&mut self, slice: &[T]) {
 | 
			
		||||
		Vec::<T>::extend_from_slice(self, slice)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_veclike_for_elastic_array {
 | 
			
		||||
	($from: ident) => {
 | 
			
		||||
		impl<T> VecLike<T> for $from<T> where T: Copy {
 | 
			
		||||
			fn vec_push(&mut self, value: T) {
 | 
			
		||||
				$from::<T>::push(self, value)
 | 
			
		||||
			}
 | 
			
		||||
			fn vec_extend(&mut self, slice: &[T]) {
 | 
			
		||||
				$from::<T>::append_slice(self, slice)
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_veclike_for_elastic_array!(ElasticArray16);
 | 
			
		||||
impl_veclike_for_elastic_array!(ElasticArray32);
 | 
			
		||||
impl_veclike_for_elastic_array!(ElasticArray1024);
 | 
			
		||||
 | 
			
		||||
/// Slie pretty print helper
 | 
			
		||||
pub struct PrettySlice<'a> (&'a [u8]);
 | 
			
		||||
 | 
			
		||||
impl<'a> fmt::Debug for PrettySlice<'a> {
 | 
			
		||||
@ -166,223 +182,6 @@ fn bytes_convertable() {
 | 
			
		||||
	assert_eq!([0u8; 0].bytes(), &[]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Converts given type to its shortest representation in bytes
 | 
			
		||||
///
 | 
			
		||||
/// TODO: optimise some conversations
 | 
			
		||||
pub trait ToBytes {
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn to_bytes(&self) -> Vec<u8>;
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { self.to_bytes().len() }
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn first_byte(&self) -> Option<u8> { self.to_bytes().first().map(|&x| { x })}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl <'a> ToBytes for &'a str {
 | 
			
		||||
	fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
		From::from(*self)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { self.len() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToBytes for String {
 | 
			
		||||
	fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
		let s: &str = self.as_ref();
 | 
			
		||||
		From::from(s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { self.len() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToBytes for u64 {
 | 
			
		||||
	fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
		let mut res= vec![];
 | 
			
		||||
		let count = self.to_bytes_len();
 | 
			
		||||
		res.reserve(count);
 | 
			
		||||
		for i in 0..count {
 | 
			
		||||
			let j = count - 1 - i;
 | 
			
		||||
			res.push((*self >> (j * 8)) as u8);
 | 
			
		||||
		}
 | 
			
		||||
		res
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToBytes for bool {
 | 
			
		||||
	fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
		vec![ if *self { 1u8 } else { 0u8 } ]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { 1 }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_map_to_bytes {
 | 
			
		||||
	($from: ident, $to: ty) => {
 | 
			
		||||
		impl ToBytes for $from {
 | 
			
		||||
			fn to_bytes(&self) -> Vec<u8> { (*self as $to).to_bytes() }
 | 
			
		||||
			fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_map_to_bytes!(usize, u64);
 | 
			
		||||
impl_map_to_bytes!(u16, u64);
 | 
			
		||||
impl_map_to_bytes!(u32, u64);
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_uint_to_bytes {
 | 
			
		||||
	($name: ident) => {
 | 
			
		||||
		impl ToBytes for $name {
 | 
			
		||||
			fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
				let mut res= vec![];
 | 
			
		||||
				let count = self.to_bytes_len();
 | 
			
		||||
				res.reserve(count);
 | 
			
		||||
				for i in 0..count {
 | 
			
		||||
					let j = count - 1 - i;
 | 
			
		||||
					res.push(self.byte(j));
 | 
			
		||||
				}
 | 
			
		||||
				res
 | 
			
		||||
			}
 | 
			
		||||
			fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_uint_to_bytes!(U256);
 | 
			
		||||
impl_uint_to_bytes!(U128);
 | 
			
		||||
 | 
			
		||||
impl <T>ToBytes for T where T: FixedHash {
 | 
			
		||||
	fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
		let mut res: Vec<u8> = vec![];
 | 
			
		||||
		res.reserve(T::size());
 | 
			
		||||
 | 
			
		||||
		unsafe {
 | 
			
		||||
			use std::ptr;
 | 
			
		||||
			ptr::copy(self.bytes().as_ptr(), res.as_mut_ptr(), T::size());
 | 
			
		||||
			res.set_len(T::size());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		res
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Error returned when FromBytes conversation goes wrong
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum FromBytesError {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	DataIsTooShort,
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	DataIsTooLong,
 | 
			
		||||
	/// Integer-representation is non-canonically prefixed with zero byte(s).
 | 
			
		||||
	ZeroPrefixedInt,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl StdError for FromBytesError {
 | 
			
		||||
	fn description(&self) -> &str { "from_bytes error" }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for FromBytesError {
 | 
			
		||||
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
		fmt::Debug::fmt(&self, f)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Alias for the result of FromBytes trait
 | 
			
		||||
pub type FromBytesResult<T> = Result<T, FromBytesError>;
 | 
			
		||||
 | 
			
		||||
/// Converts to given type from its bytes representation
 | 
			
		||||
///
 | 
			
		||||
/// TODO: check size of bytes before conversation and return appropriate error
 | 
			
		||||
pub trait FromBytes: Sized {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromBytes for String {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
 | 
			
		||||
		Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_uint_from_bytes {
 | 
			
		||||
	($to: ident) => {
 | 
			
		||||
		impl FromBytes for $to {
 | 
			
		||||
			fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> {
 | 
			
		||||
				match bytes.len() {
 | 
			
		||||
					0 => Ok(0),
 | 
			
		||||
					l if l <= mem::size_of::<$to>() => {
 | 
			
		||||
						if bytes[0] == 0 {
 | 
			
		||||
							return Err(FromBytesError::ZeroPrefixedInt)
 | 
			
		||||
						}
 | 
			
		||||
						let mut res = 0 as $to;
 | 
			
		||||
						for i in 0..l {
 | 
			
		||||
							let shift = (l - 1 - i) * 8;
 | 
			
		||||
							res = res + ((bytes[i] as $to) << shift);
 | 
			
		||||
						}
 | 
			
		||||
						Ok(res)
 | 
			
		||||
					}
 | 
			
		||||
					_ => Err(FromBytesError::DataIsTooLong)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromBytes for bool {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<bool> {
 | 
			
		||||
		match bytes.len() {
 | 
			
		||||
			0 => Ok(false),
 | 
			
		||||
			1 => Ok(bytes[0] != 0),
 | 
			
		||||
			_ => Err(FromBytesError::DataIsTooLong),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//impl_uint_from_bytes!(u8);
 | 
			
		||||
impl_uint_from_bytes!(u16);
 | 
			
		||||
impl_uint_from_bytes!(u32);
 | 
			
		||||
impl_uint_from_bytes!(u64);
 | 
			
		||||
impl_uint_from_bytes!(usize);
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_uint_from_bytes {
 | 
			
		||||
	($name: ident) => {
 | 
			
		||||
		impl FromBytes for $name {
 | 
			
		||||
			fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
 | 
			
		||||
				if !bytes.is_empty() && bytes[0] == 0 {
 | 
			
		||||
					Err(FromBytesError::ZeroPrefixedInt)
 | 
			
		||||
				} else if bytes.len() <= $name::SIZE {
 | 
			
		||||
					Ok($name::from(bytes))
 | 
			
		||||
				} else {
 | 
			
		||||
					Err(FromBytesError::DataIsTooLong)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_uint_from_bytes!(U256);
 | 
			
		||||
impl_uint_from_bytes!(U128);
 | 
			
		||||
 | 
			
		||||
impl <T>FromBytes for T where T: FixedHash {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<T> {
 | 
			
		||||
		match bytes.len().cmp(&T::size()) {
 | 
			
		||||
			Ordering::Less => return Err(FromBytesError::DataIsTooShort),
 | 
			
		||||
			Ordering::Greater => return Err(FromBytesError::DataIsTooLong),
 | 
			
		||||
			Ordering::Equal => ()
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		unsafe {
 | 
			
		||||
			use std::{mem, ptr};
 | 
			
		||||
 | 
			
		||||
			let mut res: T = mem::uninitialized();
 | 
			
		||||
			ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size());
 | 
			
		||||
 | 
			
		||||
			Ok(res)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Simple trait to allow for raw population of a Sized object from a byte slice.
 | 
			
		||||
pub trait Populatable {
 | 
			
		||||
	/// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
 | 
			
		||||
 | 
			
		||||
@ -124,11 +124,10 @@ pub struct CapabilityInfo {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encodable for CapabilityInfo {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) -> () where E: Encoder {
 | 
			
		||||
		encoder.emit_list(|e| {
 | 
			
		||||
			self.protocol.encode(e);
 | 
			
		||||
			(self.version as u32).encode(e);
 | 
			
		||||
		});
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.begin_list(2);
 | 
			
		||||
		s.append(&self.protocol);
 | 
			
		||||
		s.append(&self.version);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -57,11 +57,10 @@ pub struct PeerCapabilityInfo {
 | 
			
		||||
 | 
			
		||||
impl Decodable for PeerCapabilityInfo {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
 | 
			
		||||
		let c = try!(decoder.as_list());
 | 
			
		||||
		let v: u32 = try!(Decodable::decode(&c[1]));
 | 
			
		||||
		let c = decoder.as_rlp();
 | 
			
		||||
		Ok(PeerCapabilityInfo {
 | 
			
		||||
			protocol: try!(Decodable::decode(&c[0])),
 | 
			
		||||
			version: v as u8,
 | 
			
		||||
			protocol: try!(c.val_at(0)),
 | 
			
		||||
			version: try!(c.val_at(1))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -199,7 +198,7 @@ impl Session {
 | 
			
		||||
	fn write_hello(&mut self, host: &HostInfo) -> Result<(), UtilError> {
 | 
			
		||||
		let mut rlp = RlpStream::new();
 | 
			
		||||
		rlp.append_raw(&[PACKET_HELLO as u8], 0);
 | 
			
		||||
		rlp.append_list(5)
 | 
			
		||||
		rlp.begin_list(5)
 | 
			
		||||
			.append(&host.protocol_version)
 | 
			
		||||
			.append(&host.client_version)
 | 
			
		||||
			.append(&host.capabilities)
 | 
			
		||||
@ -267,7 +266,7 @@ impl Session {
 | 
			
		||||
	fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError {
 | 
			
		||||
		let mut rlp = RlpStream::new();
 | 
			
		||||
		rlp.append(&(PACKET_DISCONNECT as u32));
 | 
			
		||||
		rlp.append_list(1);
 | 
			
		||||
		rlp.begin_list(1);
 | 
			
		||||
		rlp.append(&(reason.clone() as u32));
 | 
			
		||||
		self.connection.send_packet(&rlp.out()).ok();
 | 
			
		||||
		NetworkError::Disconnect(reason)
 | 
			
		||||
@ -276,7 +275,7 @@ impl Session {
 | 
			
		||||
	fn prepare(packet_id: u8) -> Result<RlpStream, UtilError> {
 | 
			
		||||
		let mut rlp = RlpStream::new();
 | 
			
		||||
		rlp.append(&(packet_id as u32));
 | 
			
		||||
		rlp.append_list(0);
 | 
			
		||||
		rlp.begin_list(0);
 | 
			
		||||
		Ok(rlp)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -143,7 +143,6 @@ impl OverlayDB {
 | 
			
		||||
			self.backing.delete(&key.bytes()).expect("Low-level database error. Some issue with your hard disk?");
 | 
			
		||||
			true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										255
									
								
								util/src/rlp/bytes.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								util/src/rlp/bytes.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,255 @@
 | 
			
		||||
//! Unified interfaces for RLP bytes operations on basic types
 | 
			
		||||
//!
 | 
			
		||||
 | 
			
		||||
use std::mem;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::cmp::Ordering;
 | 
			
		||||
use std::error::Error as StdError;
 | 
			
		||||
use uint::{Uint, U128, U256};
 | 
			
		||||
use hash::FixedHash;
 | 
			
		||||
use elastic_array::*;
 | 
			
		||||
 | 
			
		||||
/// Vector like object
 | 
			
		||||
pub trait VecLike<T> {
 | 
			
		||||
	/// Add an element to the collection
 | 
			
		||||
    fn vec_push(&mut self, value: T);
 | 
			
		||||
 | 
			
		||||
	/// Add a slice to the collection
 | 
			
		||||
    fn vec_extend(&mut self, slice: &[T]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> VecLike<T> for Vec<T> where T: Copy {
 | 
			
		||||
	fn vec_push(&mut self, value: T) {
 | 
			
		||||
		Vec::<T>::push(self, value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn vec_extend(&mut self, slice: &[T]) {
 | 
			
		||||
		Vec::<T>::extend_from_slice(self, slice)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_veclike_for_elastic_array {
 | 
			
		||||
	($from: ident) => {
 | 
			
		||||
		impl<T> VecLike<T> for $from<T> where T: Copy {
 | 
			
		||||
			fn vec_push(&mut self, value: T) {
 | 
			
		||||
				$from::<T>::push(self, value)
 | 
			
		||||
			}
 | 
			
		||||
			fn vec_extend(&mut self, slice: &[T]) {
 | 
			
		||||
				$from::<T>::append_slice(self, slice)
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_veclike_for_elastic_array!(ElasticArray16);
 | 
			
		||||
impl_veclike_for_elastic_array!(ElasticArray32);
 | 
			
		||||
impl_veclike_for_elastic_array!(ElasticArray1024);
 | 
			
		||||
 | 
			
		||||
/// Converts given type to its shortest representation in bytes
 | 
			
		||||
///
 | 
			
		||||
/// TODO: optimise some conversations
 | 
			
		||||
pub trait ToBytes {
 | 
			
		||||
	/// Serialize self to byte array
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V);
 | 
			
		||||
	/// Get length of serialized data in bytes
 | 
			
		||||
	fn to_bytes_len(&self) -> usize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl <'a> ToBytes for &'a str {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		out.vec_extend(self.as_bytes());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize {
 | 
			
		||||
		self.as_bytes().len()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToBytes for String {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		out.vec_extend(self.as_bytes());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize {
 | 
			
		||||
		self.len()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToBytes for u64 {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		let count = self.to_bytes_len();
 | 
			
		||||
		for i in 0..count {
 | 
			
		||||
			let j = count - 1 - i;
 | 
			
		||||
			out.vec_push((*self >> (j * 8)) as u8);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToBytes for bool {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		out.vec_push(if *self { 1u8 } else { 0u8 })
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { 1 }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_map_to_bytes {
 | 
			
		||||
	($from: ident, $to: ty) => {
 | 
			
		||||
		impl ToBytes for $from {
 | 
			
		||||
			fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
				(*self as $to).to_bytes(out)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_map_to_bytes!(usize, u64);
 | 
			
		||||
impl_map_to_bytes!(u16, u64);
 | 
			
		||||
impl_map_to_bytes!(u32, u64);
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_uint_to_bytes {
 | 
			
		||||
	($name: ident) => {
 | 
			
		||||
		impl ToBytes for $name {
 | 
			
		||||
			fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
				let count = self.to_bytes_len();
 | 
			
		||||
				for i in 0..count {
 | 
			
		||||
					let j = count - 1 - i;
 | 
			
		||||
					out.vec_push(self.byte(j));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_uint_to_bytes!(U256);
 | 
			
		||||
impl_uint_to_bytes!(U128);
 | 
			
		||||
 | 
			
		||||
impl <T>ToBytes for T where T: FixedHash {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		out.vec_extend(self.bytes());
 | 
			
		||||
	}
 | 
			
		||||
	fn to_bytes_len(&self) -> usize { self.bytes().len() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Error returned when FromBytes conversation goes wrong
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub enum FromBytesError {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	DataIsTooShort,
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	DataIsTooLong,
 | 
			
		||||
	/// Integer-representation is non-canonically prefixed with zero byte(s).
 | 
			
		||||
	ZeroPrefixedInt,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl StdError for FromBytesError {
 | 
			
		||||
	fn description(&self) -> &str { "from_bytes error" }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for FromBytesError {
 | 
			
		||||
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
		fmt::Debug::fmt(&self, f)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Alias for the result of FromBytes trait
 | 
			
		||||
pub type FromBytesResult<T> = Result<T, FromBytesError>;
 | 
			
		||||
 | 
			
		||||
/// Converts to given type from its bytes representation
 | 
			
		||||
///
 | 
			
		||||
/// TODO: check size of bytes before conversation and return appropriate error
 | 
			
		||||
pub trait FromBytes: Sized {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromBytes for String {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
 | 
			
		||||
		Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_uint_from_bytes {
 | 
			
		||||
	($to: ident) => {
 | 
			
		||||
		impl FromBytes for $to {
 | 
			
		||||
			fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> {
 | 
			
		||||
				match bytes.len() {
 | 
			
		||||
					0 => Ok(0),
 | 
			
		||||
					l if l <= mem::size_of::<$to>() => {
 | 
			
		||||
						if bytes[0] == 0 {
 | 
			
		||||
							return Err(FromBytesError::ZeroPrefixedInt)
 | 
			
		||||
						}
 | 
			
		||||
						let mut res = 0 as $to;
 | 
			
		||||
						for i in 0..l {
 | 
			
		||||
							let shift = (l - 1 - i) * 8;
 | 
			
		||||
							res = res + ((bytes[i] as $to) << shift);
 | 
			
		||||
						}
 | 
			
		||||
						Ok(res)
 | 
			
		||||
					}
 | 
			
		||||
					_ => Err(FromBytesError::DataIsTooLong)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromBytes for bool {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<bool> {
 | 
			
		||||
		match bytes.len() {
 | 
			
		||||
			0 => Ok(false),
 | 
			
		||||
			1 => Ok(bytes[0] != 0),
 | 
			
		||||
			_ => Err(FromBytesError::DataIsTooLong),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//impl_uint_from_bytes!(u8);
 | 
			
		||||
impl_uint_from_bytes!(u16);
 | 
			
		||||
impl_uint_from_bytes!(u32);
 | 
			
		||||
impl_uint_from_bytes!(u64);
 | 
			
		||||
impl_uint_from_bytes!(usize);
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_uint_from_bytes {
 | 
			
		||||
	($name: ident) => {
 | 
			
		||||
		impl FromBytes for $name {
 | 
			
		||||
			fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
 | 
			
		||||
				if !bytes.is_empty() && bytes[0] == 0 {
 | 
			
		||||
					Err(FromBytesError::ZeroPrefixedInt)
 | 
			
		||||
				} else if bytes.len() <= $name::SIZE {
 | 
			
		||||
					Ok($name::from(bytes))
 | 
			
		||||
				} else {
 | 
			
		||||
					Err(FromBytesError::DataIsTooLong)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_uint_from_bytes!(U256);
 | 
			
		||||
impl_uint_from_bytes!(U128);
 | 
			
		||||
 | 
			
		||||
impl <T>FromBytes for T where T: FixedHash {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<T> {
 | 
			
		||||
		match bytes.len().cmp(&T::size()) {
 | 
			
		||||
			Ordering::Less => return Err(FromBytesError::DataIsTooShort),
 | 
			
		||||
			Ordering::Greater => return Err(FromBytesError::DataIsTooLong),
 | 
			
		||||
			Ordering::Equal => ()
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		unsafe {
 | 
			
		||||
			use std::{mem, ptr};
 | 
			
		||||
 | 
			
		||||
			let mut res: T = mem::uninitialized();
 | 
			
		||||
			ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size());
 | 
			
		||||
 | 
			
		||||
			Ok(res)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,25 +30,22 @@
 | 
			
		||||
//! * You want to get view onto rlp-slice.
 | 
			
		||||
//! * You don't want to decode whole rlp at once.
 | 
			
		||||
 | 
			
		||||
/// TODO [Gav Wood] Please document me
 | 
			
		||||
pub mod rlptraits;
 | 
			
		||||
/// TODO [Gav Wood] Please document me
 | 
			
		||||
pub mod rlperrors;
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
pub mod rlpin;
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
pub mod untrusted_rlp;
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
pub mod rlpstream;
 | 
			
		||||
mod rlperrors;
 | 
			
		||||
mod rlpin;
 | 
			
		||||
mod untrusted_rlp;
 | 
			
		||||
mod rlpstream;
 | 
			
		||||
mod bytes;
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests;
 | 
			
		||||
 | 
			
		||||
pub use self::rlperrors::DecoderError;
 | 
			
		||||
pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder};
 | 
			
		||||
pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder, RlpEncodable, RlpDecodable};
 | 
			
		||||
pub use self::untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype};
 | 
			
		||||
pub use self::rlpin::{Rlp, RlpIterator};
 | 
			
		||||
pub use self::rlpstream::{RlpStream,RlpStandard};
 | 
			
		||||
pub use self::rlpstream::{RlpStream};
 | 
			
		||||
pub use elastic_array::ElasticArray1024;
 | 
			
		||||
use super::hash::H256;
 | 
			
		||||
 | 
			
		||||
/// TODO [arkpar] Please document me
 | 
			
		||||
@ -72,7 +69,7 @@ pub const SHA3_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7,
 | 
			
		||||
/// 	assert_eq!(animals, vec!["cat".to_string(), "dog".to_string()]);
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
pub fn decode<T>(bytes: &[u8]) -> T where T: Decodable {
 | 
			
		||||
pub fn decode<T>(bytes: &[u8]) -> T where T: RlpDecodable {
 | 
			
		||||
	let rlp = Rlp::new(bytes);
 | 
			
		||||
	rlp.as_val()
 | 
			
		||||
}
 | 
			
		||||
@ -84,13 +81,13 @@ pub fn decode<T>(bytes: &[u8]) -> T where T: Decodable {
 | 
			
		||||
/// use util::rlp::*;
 | 
			
		||||
///
 | 
			
		||||
/// fn main () {
 | 
			
		||||
/// 	let animals = vec!["cat", "dog"];
 | 
			
		||||
/// 	let out = encode(&animals);
 | 
			
		||||
/// 	assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']);
 | 
			
		||||
/// 	let animal = "cat";
 | 
			
		||||
/// 	let out = encode(&animal).to_vec();
 | 
			
		||||
/// 	assert_eq!(out, vec![0x83, b'c', b'a', b't']);
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
pub fn encode<E>(object: &E) -> Vec<u8> where E: Encodable {
 | 
			
		||||
pub fn encode<E>(object: &E) -> ElasticArray1024<u8> where E: RlpEncodable {
 | 
			
		||||
	let mut stream = RlpStream::new();
 | 
			
		||||
	stream.append(object);
 | 
			
		||||
	stream.out()
 | 
			
		||||
	stream.drain()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::error::Error as StdError;
 | 
			
		||||
use bytes::FromBytesError;
 | 
			
		||||
use rlp::bytes::FromBytesError;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use rlp::{View, Decodable, DecoderError, UntrustedRlp, PayloadInfo, Prototype};
 | 
			
		||||
use rlp::{View, DecoderError, UntrustedRlp, PayloadInfo, Prototype, RlpDecodable};
 | 
			
		||||
 | 
			
		||||
impl<'a> From<UntrustedRlp<'a>> for Rlp<'a> {
 | 
			
		||||
	fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> {
 | 
			
		||||
@ -88,28 +88,28 @@ impl<'a, 'view> View<'a, 'view> for Rlp<'a> where 'a: 'view {
 | 
			
		||||
		self.into_iter()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
 | 
			
		||||
	fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable {
 | 
			
		||||
		self.rlp.as_val()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
 | 
			
		||||
	fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable {
 | 
			
		||||
		self.at(index).rlp.as_val()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl <'a, 'view> Rlp<'a> where 'a: 'view {
 | 
			
		||||
	fn view_as_val<T, R>(r: &R) -> T where R: View<'a, 'view>, T: Decodable {
 | 
			
		||||
	fn view_as_val<T, R>(r: &R) -> T where R: View<'a, 'view>, T: RlpDecodable {
 | 
			
		||||
		let res: Result<T, DecoderError> = r.as_val();
 | 
			
		||||
		res.unwrap_or_else(|_| panic!())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	pub fn as_val<T>(&self) -> T where T: Decodable {
 | 
			
		||||
	pub fn as_val<T>(&self) -> T where T: RlpDecodable {
 | 
			
		||||
		Self::view_as_val(self)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	pub fn val_at<T>(&self, index: usize) -> T where T: Decodable {
 | 
			
		||||
	pub fn val_at<T>(&self, index: usize) -> T where T: RlpDecodable {
 | 
			
		||||
		Self::view_as_val(&self.at(index))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use std::ops::Deref;
 | 
			
		||||
use elastic_array::*;
 | 
			
		||||
use bytes::{Bytes, ToBytes};
 | 
			
		||||
use rlp::bytes::{ToBytes, VecLike};
 | 
			
		||||
use rlp::{Stream, Encoder, Encodable};
 | 
			
		||||
use hash::H256;
 | 
			
		||||
use sha3::*;
 | 
			
		||||
use rlp::rlptraits::{ByteEncodable, RlpEncodable};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone)]
 | 
			
		||||
struct ListInfo {
 | 
			
		||||
@ -25,6 +25,7 @@ impl ListInfo {
 | 
			
		||||
pub struct RlpStream {
 | 
			
		||||
	unfinished_lists: ElasticArray16<ListInfo>,
 | 
			
		||||
	encoder: BasicEncoder,
 | 
			
		||||
	finished_list: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Stream for RlpStream {
 | 
			
		||||
@ -32,27 +33,27 @@ impl Stream for RlpStream {
 | 
			
		||||
		RlpStream {
 | 
			
		||||
			unfinished_lists: ElasticArray16::new(),
 | 
			
		||||
			encoder: BasicEncoder::new(),
 | 
			
		||||
			finished_list: false,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn new_list(len: usize) -> Self {
 | 
			
		||||
		let mut stream = RlpStream::new();
 | 
			
		||||
		stream.append_list(len);
 | 
			
		||||
		stream.begin_list(len);
 | 
			
		||||
		stream
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn append<E>(&mut self, object: &E) -> &mut RlpStream where E: Encodable {
 | 
			
		||||
		// encode given value and add it at the end of the stream
 | 
			
		||||
		object.encode(&mut self.encoder);
 | 
			
		||||
 | 
			
		||||
		// if list is finished, prepend the length
 | 
			
		||||
		self.note_appended(1);
 | 
			
		||||
 | 
			
		||||
		// return chainable self
 | 
			
		||||
	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 append_list(&mut self, len: usize) -> &mut RlpStream {
 | 
			
		||||
	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
 | 
			
		||||
@ -117,6 +118,21 @@ impl Stream for RlpStream {
 | 
			
		||||
 | 
			
		||||
impl RlpStream {
 | 
			
		||||
 | 
			
		||||
	/// Appends primitive value to the end of stream
 | 
			
		||||
	fn append_value<E>(&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 {
 | 
			
		||||
@ -141,6 +157,7 @@ impl RlpStream {
 | 
			
		||||
			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.
 | 
			
		||||
@ -164,12 +181,12 @@ impl BasicEncoder {
 | 
			
		||||
	/// 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 = vec![];
 | 
			
		||||
		let mut res = ElasticArray16::new();
 | 
			
		||||
		match len {
 | 
			
		||||
			0...55 => res.push(0xc0u8 + len as u8),
 | 
			
		||||
			_ => {
 | 
			
		||||
				res.push(0xf7u8 + len.to_bytes_len() as u8);
 | 
			
		||||
				res.extend(len.to_bytes());
 | 
			
		||||
				ToBytes::to_bytes(&len, &mut res);
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
@ -183,22 +200,30 @@ impl BasicEncoder {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Encoder for BasicEncoder {
 | 
			
		||||
	fn emit_value(&mut self, bytes: &[u8]) -> () {
 | 
			
		||||
		match bytes.len() {
 | 
			
		||||
	fn emit_value<E: ByteEncodable>(&mut self, value: &E) {
 | 
			
		||||
		match value.bytes_len() {
 | 
			
		||||
			// just 0
 | 
			
		||||
			0 => self.bytes.push(0x80u8),
 | 
			
		||||
			// byte is its own encoding
 | 
			
		||||
			1 if bytes[0] < 0x80 => self.bytes.append_slice(bytes),
 | 
			
		||||
			// 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 @ 1 ... 55 => {
 | 
			
		||||
			len @ 2 ... 55 => {
 | 
			
		||||
				self.bytes.push(0x80u8 + len as u8);
 | 
			
		||||
				self.bytes.append_slice(bytes);
 | 
			
		||||
				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);
 | 
			
		||||
				self.bytes.append_slice(&len.to_bytes());
 | 
			
		||||
				self.bytes.append_slice(bytes);
 | 
			
		||||
				ToBytes::to_bytes(&len, &mut self.bytes);
 | 
			
		||||
				value.to_bytes(&mut self.bytes);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -206,86 +231,82 @@ impl Encoder for BasicEncoder {
 | 
			
		||||
	fn emit_raw(&mut self, bytes: &[u8]) -> () {
 | 
			
		||||
		self.bytes.append_slice(bytes);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> () {
 | 
			
		||||
		// get len before inserting a list
 | 
			
		||||
		let before_len = self.bytes.len();
 | 
			
		||||
impl<T> ByteEncodable for T where T: ToBytes {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		ToBytes::to_bytes(self, out)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		// insert all list elements
 | 
			
		||||
		f(self);
 | 
			
		||||
 | 
			
		||||
		// get len after inserting a list
 | 
			
		||||
		let after_len = self.bytes.len();
 | 
			
		||||
 | 
			
		||||
		// diff is list len
 | 
			
		||||
		let list_len = after_len - before_len;
 | 
			
		||||
		self.insert_list_len_at_pos(list_len, before_len);
 | 
			
		||||
	fn bytes_len(&self) -> usize {
 | 
			
		||||
		ToBytes::to_bytes_len(self)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// TODO [Gav Wood] Please document me
 | 
			
		||||
pub trait RlpStandard {
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream);
 | 
			
		||||
struct U8Slice<'a>(&'a [u8]);
 | 
			
		||||
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn rlp_bytes(&self) -> Bytes {
 | 
			
		||||
		let mut s = RlpStream::new();
 | 
			
		||||
		self.rlp_append(&mut s);
 | 
			
		||||
		s.out()
 | 
			
		||||
impl<'a> ByteEncodable for U8Slice<'a> {
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		out.vec_extend(self.0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn rlp_sha3(&self) -> H256 { self.rlp_bytes().sha3() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @debris TODO: implement Encoder for RlpStandard.
 | 
			
		||||
 | 
			
		||||
impl<T> Encodable for T where T: ToBytes {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_value(&self.to_bytes())
 | 
			
		||||
	fn bytes_len(&self) -> usize {
 | 
			
		||||
		self.0.len()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a, T> Encodable for &'a [T] where T: Encodable + 'a {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_list(|e| {
 | 
			
		||||
			// insert all list elements
 | 
			
		||||
			for el in self.iter() {
 | 
			
		||||
				el.encode(e);
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
impl<'a> Encodable for &'a[u8] {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.append_value(&U8Slice(self))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> Encodable for Vec<T> where T: Encodable {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		let r: &[T] = self.as_ref();
 | 
			
		||||
		r.encode(encoder)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// lets treat bytes differently than other lists
 | 
			
		||||
/// they are a single value
 | 
			
		||||
impl<'a> Encodable for &'a [u8] {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_value(self)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// lets treat bytes differently than other lists
 | 
			
		||||
/// they are a single value
 | 
			
		||||
impl Encodable for Vec<u8> {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		encoder.emit_value(self)
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		s.append_value(&U8Slice(self.deref()))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> Encodable for Option<T> where T: Encodable {
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) where E: Encoder {
 | 
			
		||||
		match *self {
 | 
			
		||||
			Some(ref x) => x.encode(encoder),
 | 
			
		||||
			None => encoder.emit_value(&[])
 | 
			
		||||
impl<T> 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<V: VecLike<u8>>(&self, out: &mut V) {
 | 
			
		||||
		out.vec_push(self.0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn bytes_len(&self) -> usize { 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<T> Encodable for Vec<T>  where T: Encodable {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		Encodable::rlp_append(&self.deref(), s);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> RlpEncodable for T where T: Encodable {
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream) {
 | 
			
		||||
		Encodable::rlp_append(self, s)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,11 @@
 | 
			
		||||
//! Common RLP traits
 | 
			
		||||
use std::ops::Deref;
 | 
			
		||||
use rlp::bytes::VecLike;
 | 
			
		||||
use rlp::{DecoderError, UntrustedRlp};
 | 
			
		||||
use rlp::rlpstream::RlpStream;
 | 
			
		||||
use elastic_array::ElasticArray1024;
 | 
			
		||||
use hash::H256;
 | 
			
		||||
use sha3::*;
 | 
			
		||||
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
pub trait Decoder: Sized {
 | 
			
		||||
@ -6,17 +13,21 @@ pub trait Decoder: Sized {
 | 
			
		||||
	fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
 | 
			
		||||
		where F: FnOnce(&[u8]) -> Result<T, DecoderError>;
 | 
			
		||||
 | 
			
		||||
	/// TODO [arkpar] Please document me
 | 
			
		||||
	fn as_list(&self) -> Result<Vec<Self>, DecoderError>;
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn as_rlp(&self) -> &UntrustedRlp;
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn as_raw(&self) -> &[u8];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
/// RLP decodable trait
 | 
			
		||||
pub trait Decodable: Sized {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	/// Decode a value from RLP bytes
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError>  where D: Decoder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Internal helper trait. Implement `Decodable` for custom types.
 | 
			
		||||
pub trait RlpDecodable: Sized {
 | 
			
		||||
	/// Decode a value from RLP bytes
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError>  where D: Decoder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -195,26 +206,48 @@ pub trait View<'a, 'view>: Sized {
 | 
			
		||||
	fn iter(&'view self) -> Self::Iter;
 | 
			
		||||
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable;
 | 
			
		||||
	fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable;
 | 
			
		||||
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable;
 | 
			
		||||
	fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
pub trait Encoder {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn emit_value(&mut self, bytes: &[u8]) -> ();
 | 
			
		||||
	/// TODO [Gav Wood] Please document me
 | 
			
		||||
	fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ();
 | 
			
		||||
	fn emit_value<E: ByteEncodable>(&mut self, value: &E);
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn emit_raw(&mut self, bytes: &[u8]) -> ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
/// Primitive data type encodable to RLP
 | 
			
		||||
pub trait ByteEncodable {
 | 
			
		||||
	/// Serialize this object to given byte container
 | 
			
		||||
	fn to_bytes<V: VecLike<u8>>(&self, out: &mut V);
 | 
			
		||||
	/// Get size of serialised data in bytes
 | 
			
		||||
	fn bytes_len(&self) -> usize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Structure encodable to RLP. Implement this trait for 
 | 
			
		||||
pub trait Encodable {
 | 
			
		||||
	/// TODO [debris] Please document me
 | 
			
		||||
	fn encode<E>(&self, encoder: &mut E) -> () where E: Encoder;
 | 
			
		||||
	/// Append a value to the stream
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream);
 | 
			
		||||
 | 
			
		||||
	/// Get rlp-encoded bytes for this instance
 | 
			
		||||
	fn rlp_bytes(&self) -> ElasticArray1024<u8> {
 | 
			
		||||
		let mut s = RlpStream::new();
 | 
			
		||||
		self.rlp_append(&mut s);
 | 
			
		||||
		s.drain()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Get the hash or RLP encoded representation
 | 
			
		||||
	fn rlp_sha3(&self) -> H256 { self.rlp_bytes().deref().sha3() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Encodable wrapper trait required to handle special case of encoding a &[u8] as string and not as list
 | 
			
		||||
pub trait RlpEncodable {
 | 
			
		||||
	/// Append a value to the stream
 | 
			
		||||
	fn rlp_append(&self, s: &mut RlpStream);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// TODO [debris] Please document me
 | 
			
		||||
@ -239,7 +272,7 @@ pub trait Stream: Sized {
 | 
			
		||||
	/// 	assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']);
 | 
			
		||||
	/// }
 | 
			
		||||
	/// ```
 | 
			
		||||
	fn append<'a, E>(&'a mut self, object: &E) -> &'a mut Self where E: Encodable;
 | 
			
		||||
	fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable;
 | 
			
		||||
 | 
			
		||||
	/// Declare appending the list of given size, chainable.
 | 
			
		||||
	///
 | 
			
		||||
@ -249,13 +282,13 @@ pub trait Stream: Sized {
 | 
			
		||||
	///
 | 
			
		||||
	/// fn main () {
 | 
			
		||||
	/// 	let mut stream = RlpStream::new_list(2);
 | 
			
		||||
	/// 	stream.append_list(2).append(&"cat").append(&"dog");
 | 
			
		||||
	/// 	stream.begin_list(2).append(&"cat").append(&"dog");
 | 
			
		||||
	/// 	stream.append(&"");
 | 
			
		||||
	/// 	let out = stream.out();
 | 
			
		||||
	/// 	assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]);
 | 
			
		||||
	/// }
 | 
			
		||||
	/// ```
 | 
			
		||||
	fn append_list(&mut self, len: usize) -> &mut Self;
 | 
			
		||||
	fn begin_list(&mut self, len: usize) -> &mut Self;
 | 
			
		||||
 | 
			
		||||
	/// Apends null to the end of stream, chainable.
 | 
			
		||||
	///
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@ fn rlp_at() {
 | 
			
		||||
	{
 | 
			
		||||
		let rlp = UntrustedRlp::new(&data);
 | 
			
		||||
		assert!(rlp.is_list());
 | 
			
		||||
		//let animals = <Vec<String> as rlp::Decodable>::decode_untrusted(&rlp).unwrap();
 | 
			
		||||
		//let animals = <Vec<String> as rlp::RlpDecodable>::decode_untrusted(&rlp).unwrap();
 | 
			
		||||
		let animals: Vec<String> = rlp.as_val().unwrap();
 | 
			
		||||
		assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]);
 | 
			
		||||
 | 
			
		||||
@ -83,7 +83,7 @@ fn run_encode_tests<T>(tests: Vec<ETestPair<T>>)
 | 
			
		||||
{
 | 
			
		||||
	for t in &tests {
 | 
			
		||||
		let res = rlp::encode(&t.0);
 | 
			
		||||
		assert_eq!(res, &t.1[..]);
 | 
			
		||||
		assert_eq!(&res[..], &t.1[..]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -193,15 +193,9 @@ fn encode_vector_str() {
 | 
			
		||||
	run_encode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn encode_vector_of_vectors_str() {
 | 
			
		||||
	let tests = vec![ETestPair(vec![vec!["cat"]], vec![0xc5, 0xc4, 0x83, b'c', b'a', b't'])];
 | 
			
		||||
	run_encode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
struct DTestPair<T>(T, Vec<u8>) where T: rlp::RlpDecodable + fmt::Debug + cmp::Eq;
 | 
			
		||||
 | 
			
		||||
struct DTestPair<T>(T, Vec<u8>) where T: rlp::Decodable + fmt::Debug + cmp::Eq;
 | 
			
		||||
 | 
			
		||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: rlp::Decodable + fmt::Debug + cmp::Eq {
 | 
			
		||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: rlp::RlpDecodable + fmt::Debug + cmp::Eq {
 | 
			
		||||
	for t in &tests {
 | 
			
		||||
		let res: T = rlp::decode(&t.1);
 | 
			
		||||
		assert_eq!(res, t.0);
 | 
			
		||||
@ -220,12 +214,21 @@ fn decode_vector_u8() {
 | 
			
		||||
	run_decode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn decode_untrusted_u8() {
 | 
			
		||||
	let tests = vec![
 | 
			
		||||
		DTestPair(0x0u8, vec![0x80]),
 | 
			
		||||
		DTestPair(0x77u8, vec![0x77]),
 | 
			
		||||
		DTestPair(0xccu8, vec![0x81, 0xcc]),
 | 
			
		||||
	];
 | 
			
		||||
	run_decode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn decode_untrusted_u16() {
 | 
			
		||||
	let tests = vec![
 | 
			
		||||
		DTestPair(0u16, vec![0u8]),
 | 
			
		||||
		DTestPair(0x100, vec![0x82, 0x01, 0x00]),
 | 
			
		||||
		DTestPair(0xffff, vec![0x82, 0xff, 0xff]),
 | 
			
		||||
		DTestPair(0x100u16, vec![0x82, 0x01, 0x00]),
 | 
			
		||||
		DTestPair(0xffffu16, vec![0x82, 0xff, 0xff]),
 | 
			
		||||
	];
 | 
			
		||||
	run_decode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
@ -233,9 +236,8 @@ fn decode_untrusted_u16() {
 | 
			
		||||
#[test]
 | 
			
		||||
fn decode_untrusted_u32() {
 | 
			
		||||
	let tests = vec![
 | 
			
		||||
		DTestPair(0u32, vec![0u8]),
 | 
			
		||||
		DTestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]),
 | 
			
		||||
		DTestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]),
 | 
			
		||||
		DTestPair(0x10000u32, vec![0x83, 0x01, 0x00, 0x00]),
 | 
			
		||||
		DTestPair(0xffffffu32, vec![0x83, 0xff, 0xff, 0xff]),
 | 
			
		||||
	];
 | 
			
		||||
	run_decode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
@ -243,9 +245,8 @@ fn decode_untrusted_u32() {
 | 
			
		||||
#[test]
 | 
			
		||||
fn decode_untrusted_u64() {
 | 
			
		||||
	let tests = vec![
 | 
			
		||||
		DTestPair(0u64, vec![0u8]),
 | 
			
		||||
		DTestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]),
 | 
			
		||||
		DTestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]),
 | 
			
		||||
		DTestPair(0x1000000u64, vec![0x84, 0x01, 0x00, 0x00, 0x00]),
 | 
			
		||||
		DTestPair(0xFFFFFFFFu64, vec![0x84, 0xff, 0xff, 0xff, 0xff]),
 | 
			
		||||
	];
 | 
			
		||||
	run_decode_tests(tests);
 | 
			
		||||
}
 | 
			
		||||
@ -333,7 +334,7 @@ fn test_rlp_json() {
 | 
			
		||||
		for operation in input.into_iter() {
 | 
			
		||||
			match operation {
 | 
			
		||||
				rlptest::Operation::Append(ref v) => stream.append(v),
 | 
			
		||||
				rlptest::Operation::AppendList(len) => stream.append_list(len),
 | 
			
		||||
				rlptest::Operation::AppendList(len) => stream.begin_list(len),
 | 
			
		||||
				rlptest::Operation::AppendRaw(ref raw, len) => stream.append_raw(raw, len),
 | 
			
		||||
				rlptest::Operation::AppendEmpty => stream.append_empty_data()
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use std::cell::Cell;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use rustc_serialize::hex::ToHex;
 | 
			
		||||
use bytes::{FromBytes};
 | 
			
		||||
use rlp::{View, Decoder, Decodable, DecoderError};
 | 
			
		||||
use rlp::bytes::{FromBytes, FromBytesResult, FromBytesError};
 | 
			
		||||
use rlp::{View, Decoder, Decodable, DecoderError, RlpDecodable};
 | 
			
		||||
 | 
			
		||||
/// rlp offset
 | 
			
		||||
#[derive(Copy, Clone, Debug)]
 | 
			
		||||
@ -211,12 +211,12 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
 | 
			
		||||
		self.into_iter()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
 | 
			
		||||
	fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable {
 | 
			
		||||
		// optimize, so it doesn't use clone (although This clone is cheap)
 | 
			
		||||
		T::decode(&BasicDecoder::new(self.clone()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
 | 
			
		||||
	fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable {
 | 
			
		||||
		try!(self.at(index)).as_val()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -369,13 +369,6 @@ impl<'a> Decoder for BasicDecoder<'a> {
 | 
			
		||||
		self.rlp.as_raw()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn as_list(&self) -> Result<Vec<Self>, DecoderError> {
 | 
			
		||||
		let v: Vec<BasicDecoder<'a>> = self.rlp.iter()
 | 
			
		||||
			.map(BasicDecoder::new)
 | 
			
		||||
			.collect();
 | 
			
		||||
		Ok(v)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn as_rlp(&self) -> &UntrustedRlp {
 | 
			
		||||
		&self.rlp
 | 
			
		||||
	}
 | 
			
		||||
@ -391,8 +384,7 @@ impl<T> Decodable for T where T: FromBytes {
 | 
			
		||||
 | 
			
		||||
impl<T> Decodable for Vec<T> where T: Decodable {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError>  where D: Decoder {
 | 
			
		||||
		let decoders = try!(decoder.as_list());
 | 
			
		||||
		decoders.iter().map(|d| T::decode(d)).collect()
 | 
			
		||||
		decoder.as_rlp().iter().map(|d| T::decode(&BasicDecoder::new(d))).collect()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -423,15 +415,15 @@ macro_rules! impl_array_decodable {
 | 
			
		||||
		impl<T> Decodable for [T; $len] where T: Decodable {
 | 
			
		||||
			#[allow(len_zero)]
 | 
			
		||||
			fn decode<D>(decoder: &D) -> Result<Self, DecoderError>  where D: Decoder {
 | 
			
		||||
				let decoders = try!(decoder.as_list());
 | 
			
		||||
				let decoders = decoder.as_rlp();
 | 
			
		||||
 | 
			
		||||
				let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() };
 | 
			
		||||
				if decoders.len() != $len {
 | 
			
		||||
				if decoders.item_count() != $len {
 | 
			
		||||
					return Err(DecoderError::RlpIncorrectListLen);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for i in 0..decoders.len() {
 | 
			
		||||
					result[i] = try!(T::decode(&decoders[i]));
 | 
			
		||||
				for i in 0..decoders.item_count() {
 | 
			
		||||
					result[i] = try!(T::decode(&BasicDecoder::new(try!(decoders.at(i)))));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				Ok(result)
 | 
			
		||||
@ -454,6 +446,36 @@ impl_array_decodable_recursive!(
 | 
			
		||||
	32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
impl<T> RlpDecodable for T where T: Decodable {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError>  where D: Decoder {
 | 
			
		||||
		Decodable::decode(decoder)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct DecodableU8 (u8);
 | 
			
		||||
 | 
			
		||||
impl FromBytes for DecodableU8 {
 | 
			
		||||
	fn from_bytes(bytes: &[u8]) -> FromBytesResult<DecodableU8> {
 | 
			
		||||
		match bytes.len() {
 | 
			
		||||
			0 => Ok(DecodableU8(0u8)),
 | 
			
		||||
			1 => {
 | 
			
		||||
				if bytes[0] == 0 {
 | 
			
		||||
					return Err(FromBytesError::ZeroPrefixedInt)
 | 
			
		||||
				}
 | 
			
		||||
				Ok(DecodableU8(bytes[0]))
 | 
			
		||||
			}
 | 
			
		||||
			_ => Err(FromBytesError::DataIsTooLong)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl RlpDecodable for u8 {
 | 
			
		||||
	fn decode<D>(decoder: &D) -> Result<Self, DecoderError>  where D: Decoder {
 | 
			
		||||
		let u: DecodableU8 = try!(Decodable::decode(decoder));
 | 
			
		||||
		Ok(u.0)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_rlp_display() {
 | 
			
		||||
	use rustc_serialize::hex::FromHex;
 | 
			
		||||
 | 
			
		||||
@ -89,17 +89,17 @@ impl<'a> Node<'a> {
 | 
			
		||||
		let mut stream = RlpStream::new();
 | 
			
		||||
		match *self {
 | 
			
		||||
			Node::Leaf(ref slice, ref value) => {
 | 
			
		||||
				stream.append_list(2);
 | 
			
		||||
				stream.begin_list(2);
 | 
			
		||||
				stream.append(&slice.encoded(true));
 | 
			
		||||
				stream.append(value);
 | 
			
		||||
			},
 | 
			
		||||
			Node::Extension(ref slice, ref raw_rlp) => {
 | 
			
		||||
				stream.append_list(2);
 | 
			
		||||
				stream.begin_list(2);
 | 
			
		||||
				stream.append(&slice.encoded(false));
 | 
			
		||||
				stream.append_raw(raw_rlp, 1);
 | 
			
		||||
			},
 | 
			
		||||
			Node::Branch(ref nodes, ref value) => {
 | 
			
		||||
				stream.append_list(17);
 | 
			
		||||
				stream.begin_list(17);
 | 
			
		||||
				for i in 0..16 {
 | 
			
		||||
					stream.append_raw(nodes[i], 1);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@ -671,7 +671,6 @@ mod tests {
 | 
			
		||||
	use super::*;
 | 
			
		||||
	use nibbleslice::*;
 | 
			
		||||
	use rlp::*;
 | 
			
		||||
	use env_logger;
 | 
			
		||||
	use rand::random;
 | 
			
		||||
	use std::collections::HashSet;
 | 
			
		||||
	use bytes::{ToPretty,Bytes,Populatable};
 | 
			
		||||
@ -689,11 +688,11 @@ mod tests {
 | 
			
		||||
	
 | 
			
		||||
	fn random_value_indexed(j: usize) -> Bytes {
 | 
			
		||||
		match random::<usize>() % 2 {
 | 
			
		||||
			0 => encode(&j),
 | 
			
		||||
			0 => encode(&j).to_vec(),
 | 
			
		||||
			_ => {
 | 
			
		||||
				let mut h = H256::new();
 | 
			
		||||
				h.as_slice_mut()[31] = j as u8;
 | 
			
		||||
				encode(&h)
 | 
			
		||||
				encode(&h).to_vec()
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -727,7 +726,6 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
	#[test]
 | 
			
		||||
	fn playpen() {
 | 
			
		||||
		env_logger::init().ok();
 | 
			
		||||
 | 
			
		||||
		/*let maps = map!{
 | 
			
		||||
			"six-low" => StandardMap{alphabet: Alphabet::Low, min_key: 6, journal_key: 0, count: 1000},
 | 
			
		||||
@ -1040,7 +1038,7 @@ mod tests {
 | 
			
		||||
			let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
 | 
			
		||||
			for j in 0..4u32 {
 | 
			
		||||
				let key = random_key(alphabet, 5, 1);
 | 
			
		||||
				x.push((key, encode(&j)));
 | 
			
		||||
				x.push((key, encode(&j).to_vec()));
 | 
			
		||||
			}
 | 
			
		||||
			let real = trie_root(x.clone());
 | 
			
		||||
			let mut memdb = MemoryDB::new();
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ pub fn ordered_trie_root(input: Vec<Vec<u8>>) -> H256 {
 | 
			
		||||
		// optimize it later
 | 
			
		||||
		.into_iter()
 | 
			
		||||
		.enumerate()
 | 
			
		||||
		.fold(BTreeMap::new(), | mut acc, (i, vec) | { acc.insert(rlp::encode(&i), vec); acc })
 | 
			
		||||
		.fold(BTreeMap::new(), | mut acc, (i, vec) | { acc.insert(rlp::encode(&i).to_vec(), vec); acc })
 | 
			
		||||
		// then move them to a vector
 | 
			
		||||
		.into_iter()
 | 
			
		||||
		.map(|(k, v)| (as_nibbles(&k), v) )
 | 
			
		||||
@ -189,7 +189,7 @@ fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStre
 | 
			
		||||
	// if the slice contains just one item, append the suffix of the key
 | 
			
		||||
	// and then append value
 | 
			
		||||
	if inlen == 1 {
 | 
			
		||||
		stream.append_list(2);
 | 
			
		||||
		stream.begin_list(2);
 | 
			
		||||
		stream.append(&hex_prefix_encode(&key[pre_len..], true));
 | 
			
		||||
		stream.append(&value);
 | 
			
		||||
		return;
 | 
			
		||||
@ -208,7 +208,7 @@ fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStre
 | 
			
		||||
	// new part of the key to the stream
 | 
			
		||||
	// then recursively append suffixes of all items who had this key
 | 
			
		||||
	if shared_prefix > pre_len {
 | 
			
		||||
		stream.append_list(2);
 | 
			
		||||
		stream.begin_list(2);
 | 
			
		||||
		stream.append(&hex_prefix_encode(&key[pre_len..shared_prefix], false));
 | 
			
		||||
		hash256aux(input, shared_prefix, stream);
 | 
			
		||||
		return;
 | 
			
		||||
@ -216,7 +216,7 @@ fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStre
 | 
			
		||||
 | 
			
		||||
	// an item for every possible nibble/suffix
 | 
			
		||||
	// + 1 for data
 | 
			
		||||
	stream.append_list(17);
 | 
			
		||||
	stream.begin_list(17);
 | 
			
		||||
 | 
			
		||||
	// if first key len is equal to prefix_len, move to next element
 | 
			
		||||
	let mut begin = match pre_len == key.len() {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user