From 811df8a713a7650270941e73bea10dc0f88f0d38 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sun, 5 Apr 2015 19:10:37 -0500 Subject: [PATCH] Giant collection of fixes ... we are into lifetime errors now :) --- src/blockdata/block.rs | 3 +- src/blockdata/blockchain.rs | 44 ++++---- src/blockdata/opcodes.rs | 28 ++--- src/blockdata/script.rs | 53 +++++----- src/blockdata/transaction.rs | 20 ++-- src/blockdata/utxoset.rs | 4 +- src/internal_macros.rs | 72 ++++++------- src/macros.rs | 37 +++++-- src/network/address.rs | 8 +- src/network/constants.rs | 8 +- src/network/encodable.rs | 174 ++++++++++++++++--------------- src/network/message.rs | 14 +-- src/network/message_blockdata.rs | 8 +- src/network/message_network.rs | 8 +- src/network/serialize.rs | 60 ++++++----- src/util/base58.rs | 4 +- src/util/error.rs | 3 - src/util/hash.rs | 61 ++++++----- src/util/iter.rs | 26 +++-- src/util/patricia_tree.rs | 32 ++++-- src/util/uint.rs | 48 ++++++--- 21 files changed, 399 insertions(+), 316 deletions(-) diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index d4bb8de..0585be6 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -97,7 +97,7 @@ impl BlockHeader { /// Performs an SPV validation of a block, which confirms that the proof-of-work /// is correct, but does not verify that the transactions are valid or encoded /// correctly. - pub fn spv_validate(&self, required_target: &Uint256) -> error::Result<()> { + pub fn spv_validate(&self, required_target: &Uint256) -> Result<(), error::Error> { let ref target = self.target(); if target != required_target { return Err(SpvBadTarget); @@ -132,7 +132,6 @@ impl BitcoinHash for Block { } impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce); -impl_json!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce); impl_consensus_encoding!(Block, header, txdata); impl_consensus_encoding!(LoneBlockHeader, header, tx_count); diff --git a/src/blockdata/blockchain.rs b/src/blockdata/blockchain.rs index 6f6e832..c8168a2 100644 --- a/src/blockdata/blockchain.rs +++ b/src/blockdata/blockchain.rs @@ -80,9 +80,9 @@ impl BlockchainNode { } } -impl, E> ConsensusEncodable for BlockchainNode { +impl ConsensusEncodable for BlockchainNode { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(self.block.consensus_encode(s)); try!(self.total_work.consensus_encode(s)); try!(self.required_difficulty.consensus_encode(s)); @@ -93,9 +93,9 @@ impl, E> ConsensusEncodable for BlockchainNode { } } -impl, E> ConsensusDecodable for BlockchainNode { +impl ConsensusDecodable for BlockchainNode { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { Ok(BlockchainNode { block: try!(ConsensusDecodable::consensus_decode(d)), total_work: try!(ConsensusDecodable::consensus_decode(d)), @@ -123,9 +123,9 @@ pub struct Blockchain { genesis_hash: Sha256dHash } -impl, E> ConsensusEncodable for Blockchain { +impl ConsensusEncodable for Blockchain { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(self.network.consensus_encode(s)); try!(self.tree.consensus_encode(s)); try!(self.best_hash.consensus_encode(s)); @@ -134,8 +134,8 @@ impl, E> ConsensusEncodable for Blockchain { } } -impl, E> ConsensusDecodable for Blockchain { - fn consensus_decode(d: &mut D) -> Result { +impl ConsensusDecodable for Blockchain { + fn consensus_decode(d: &mut D) -> Result { let network: Network = try!(ConsensusDecodable::consensus_decode(d)); let mut tree: BlockTree = try!(ConsensusDecodable::consensus_decode(d)); let best_hash: Sha256dHash = try!(ConsensusDecodable::consensus_decode(d)); @@ -204,7 +204,9 @@ impl LocatorHashIter { } } -impl Iterator for LocatorHashIter { +impl Iterator for LocatorHashIter { + type Item = Sha256dHash; + fn next(&mut self) -> Option { if self.index.is_null() { return None; @@ -274,7 +276,9 @@ pub struct RevStaleBlockIter<'tree> { chain: &'tree Blockchain } -impl<'tree> Iterator<&'tree BlockchainNode> for BlockIter<'tree> { +impl<'tree> Iterator for BlockIter<'tree> { + type Item = &'tree BlockchainNode; + fn next(&mut self) -> Option<&'tree BlockchainNode> { if self.index.is_null() { return None; @@ -287,7 +291,9 @@ impl<'tree> Iterator<&'tree BlockchainNode> for BlockIter<'tree> { } } -impl<'tree> Iterator<&'tree BlockchainNode> for RevBlockIter<'tree> { +impl<'tree> Iterator for RevBlockIter<'tree> { + type Item = &'tree BlockchainNode; + fn next(&mut self) -> Option<&'tree BlockchainNode> { if self.index.is_null() { return None; @@ -300,7 +306,9 @@ impl<'tree> Iterator<&'tree BlockchainNode> for RevBlockIter<'tree> { } } -impl<'tree> Iterator<&'tree Block> for RevStaleBlockIter<'tree> { +impl<'tree> Iterator for RevStaleBlockIter<'tree> { + type Item = &'tree Block; + fn next(&mut self) -> Option<&'tree Block> { if self.index.is_null() { return None; @@ -365,7 +373,7 @@ impl Blockchain { } } - fn replace_txdata(&mut self, hash: &Uint256, txdata: Vec, has_txdata: bool) -> error::Result<()> { + fn replace_txdata(&mut self, hash: &Uint256, txdata: Vec, has_txdata: bool) -> Result<(), error::Error> { match self.tree.lookup_mut(hash, 256) { Some(existing_block) => { unsafe { @@ -405,26 +413,26 @@ impl Blockchain { } /// Locates a block in the chain and overwrites its txdata - pub fn add_txdata(&mut self, block: Block) -> error::Result<()> { + pub fn add_txdata(&mut self, block: Block) -> Result<(), error::Error> { self.replace_txdata(&block.header.bitcoin_hash().into_le(), block.txdata, true) } /// Locates a block in the chain and removes its txdata - pub fn remove_txdata(&mut self, hash: Sha256dHash) -> error::Result<()> { + pub fn remove_txdata(&mut self, hash: Sha256dHash) -> Result<(), error::Error> { self.replace_txdata(&hash.into_le(), vec![], false) } /// Adds a block header to the chain - pub fn add_header(&mut self, header: BlockHeader) -> error::Result<()> { + pub fn add_header(&mut self, header: BlockHeader) -> Result<(), error::Error> { self.real_add_block(Block { header: header, txdata: vec![] }, false) } /// Adds a block to the chain - pub fn add_block(&mut self, block: Block) -> error::Result<()> { + pub fn add_block(&mut self, block: Block) -> Result<(), error::Error> { self.real_add_block(block, true) } - fn real_add_block(&mut self, block: Block, has_txdata: bool) -> error::Result<()> { + fn real_add_block(&mut self, block: Block, has_txdata: bool) -> Result<(), error::Error> { // get_prev optimizes the common case where we are extending the best tip #[inline] fn get_prev<'a>(chain: &'a Blockchain, hash: Sha256dHash) -> Option { diff --git a/src/blockdata/opcodes.rs b/src/blockdata/opcodes.rs index 6dc2eb6..ae78e71 100644 --- a/src/blockdata/opcodes.rs +++ b/src/blockdata/opcodes.rs @@ -20,7 +20,7 @@ #![allow(non_camel_case_types)] -use serialize::json; +use serde; // Heavy stick to translate between opcode types use std::mem::transmute; @@ -602,24 +602,26 @@ impl All { } } -impl, E> ConsensusDecodable for All { +impl ConsensusDecodable for All { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { Ok(All::from_u8(try!(d.read_u8()))) } } -impl, E> ConsensusEncodable for All { +impl ConsensusEncodable for All { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u8(*self as u8) } } -impl json::ToJson for All { - fn to_json(&self) -> json::Json { - json::String(self.to_string()) - } +impl serde::Serialize for All { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer, + { + serializer.visit_str(&self.to_string()) + } } /// Empty stack is also FALSE @@ -644,9 +646,11 @@ pub enum Class { Ordinary(Ordinary) } -impl json::ToJson for Class { - fn to_json(&self) -> json::Json { - json::String(self.to_string()) +impl serde::Serialize for Class { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer, + { + serializer.visit_str(&self.to_string()) } } diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 3109a53..c8e2eba 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -35,9 +35,9 @@ use crypto::digest::Digest; use crypto::ripemd160::Ripemd160; use crypto::sha1::Sha1; use crypto::sha2::Sha256; - use secp256k1::Secp256k1; use secp256k1::key::PublicKey; +use serde; use blockdata::opcodes; use blockdata::transaction::{Transaction, TxIn}; @@ -1207,9 +1207,11 @@ impl AbstractStack { } } -impl json::ToJson for Error { - fn to_json(&self) -> json::Json { - json::String(self.to_string()) +impl serde::Serialize for Error { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer, + { + serializer.visit_str(&self.to_string()) } } @@ -1238,8 +1240,6 @@ pub struct ScriptTrace { pub error: Option } -impl_json!(TraceIteration, index, opcode, op_count, executed, errored, effect, stack); - /// Hashtype of a transaction, encoded in the last byte of a signature, /// specifically in the last 5 bits `byte & 31` #[derive(PartialEq, Eq, Debug, Clone)] @@ -1337,11 +1337,11 @@ impl<'a> ops::Index> for MaybeOwned<'a> { } } -impl<'a> ops::Index> for MaybeOwned<'a> { +impl<'a> ops::Index for MaybeOwned<'a> { type Output = [u8]; #[inline] - fn index(&self, _: ops::RangeFull) -> &[u8] { + fn index(&self, _: ops::RangeFull) -> &[u8] { match *self { MaybeOwned::Owned(ref v) => &v[..], MaybeOwned::Borrowed(ref s) => &s[..] @@ -1427,16 +1427,16 @@ pub fn read_scriptbool(v: &[u8]) -> bool { } /// Read a script-encoded unsigned integer -pub fn read_uint<'a, I:Iterator<&'a u8>>(mut iter: I, size: usize) - -> Result { - let mut ret = 0; - for i in 0..size { - match iter.next() { - Some(&n) => ret += (n as usize) << (i * 8), - None => { return Err(Error::EarlyEndOfScript); } +pub fn read_uint(data: &[u8], size: usize) -> Result { + if data.len() < size { + Err(Error::EarlyEndOfScript) + } else { + let mut ret = 0; + for i in 0..size { + ret += (data[i] as usize) << (i * 8); } + Ok(ret) } - Ok(ret) } /// Check a signature -- returns an error that is currently just translated @@ -2477,31 +2477,30 @@ impl Default for Script { } // User-facing serialization -impl json::ToJson for Script { - // TODO: put this in a struct alongside an opcode decode - fn to_json(&self) -> json::Json { +impl serde::Serialize for Script { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer, + { let &Script(ref raw) = self; - let mut ret = String::new(); for dat in raw.iter() { - ret.push_char(from_digit((dat / 0x10) as usize, 16).unwrap()); - ret.push_char(from_digit((dat & 0x0f) as usize, 16).unwrap()); + serializer.visit_char(from_digit((dat / 0x10) as usize, 16).unwrap()); + serializer.visit_char(from_digit((dat & 0x0f) as usize, 16).unwrap()); } - json::String(ret) } } // Network serialization -impl, E> ConsensusEncodable for Script { +impl ConsensusEncodable for Script { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { let &Script(ref data) = self; data.consensus_encode(s) } } -impl, E> ConsensusDecodable for Script { +impl ConsensusDecodable for Script { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { Ok(Script(try!(ConsensusDecodable::consensus_decode(d)))) } } diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 671b3f4..5ec2b8a 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -24,7 +24,7 @@ //! use std::default::Default; -use serialize::json; +use serde; use util::hash::Sha256dHash; use blockdata::script::{self, Script, ScriptTrace, read_scriptbool}; @@ -123,9 +123,11 @@ pub enum Error { InputNotFound(Sha256dHash, u32), } -impl json::ToJson for Error { - fn to_json(&self) -> json::Json { - json::String(self.to_string()) +impl serde::Serialize for Error { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer, + { + serializer.visit_str(&self.to_string()) } } @@ -140,10 +142,6 @@ pub struct InputTrace { error: Option } -impl_json!(ScriptTrace, script, initial_stack, iterations, error); -impl_json!(InputTrace, input_txid, input_vout, sig_trace, - pubkey_trace, p2sh_trace, error); - /// A trace of a transaction's execution #[derive(PartialEq, Eq, Clone, Debug)] pub struct TransactionTrace { @@ -151,8 +149,6 @@ pub struct TransactionTrace { inputs: Vec } -impl_json!(TransactionTrace, txid, inputs); - impl TxIn { /// Check an input's script for validity pub fn validate(&self, @@ -304,12 +300,8 @@ impl BitcoinHash for Transaction { } impl_consensus_encoding!(TxIn, prev_hash, prev_index, script_sig, sequence); -impl_json!(TxIn, prev_hash, prev_index, script_sig, sequence); impl_consensus_encoding!(TxOut, value, script_pubkey); -impl_json!(TxOut, value, script_pubkey); impl_consensus_encoding!(Transaction, version, input, output, lock_time); -impl_json!(Transaction, version, input, output, lock_time); - #[cfg(test)] mod tests { diff --git a/src/blockdata/utxoset.rs b/src/blockdata/utxoset.rs index d46aabc..cd022bc 100644 --- a/src/blockdata/utxoset.rs +++ b/src/blockdata/utxoset.rs @@ -74,7 +74,9 @@ pub struct UtxoIterator<'a> { tx_index: u32 } -impl<'a> Iterator<(Sha256dHash, u32, &'a TxOut, u32)> for UtxoIterator<'a> { +impl<'a> Iterator for UtxoIterator<'a> { + type Item = (Sha256dHash, u32, &'a TxOut, u32); + fn next(&mut self) -> Option<(Sha256dHash, u32, &'a TxOut, u32)> { while self.current.is_some() { let current = &self.current.unwrap().outputs; diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 2b06835..e3f6764 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -14,17 +14,17 @@ macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( - impl, E> ::network::encodable::ConsensusEncodable for $thing { + impl ::network::encodable::ConsensusEncodable for $thing { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { $( try!(self.$field.consensus_encode(s)); )+ Ok(()) } } - impl, E> ::network::encodable::ConsensusDecodable for $thing { + impl ::network::encodable::ConsensusDecodable for $thing { #[inline] - fn consensus_decode(d: &mut D) -> Result<$thing, E> { + fn consensus_decode(d: &mut D) -> Result<$thing, D::Error> { use network::encodable::ConsensusDecodable; Ok($thing { $( $field: try!(ConsensusDecodable::consensus_decode(d)), )+ @@ -36,37 +36,23 @@ macro_rules! impl_consensus_encoding { macro_rules! impl_newtype_consensus_encoding { ($thing:ident) => ( - impl, E> ::network::encodable::ConsensusEncodable for $thing { + impl ::network::encodable::ConsensusEncodable for $thing { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { let &$thing(ref data) = self; data.consensus_encode(s) } } - impl, E> ::network::encodable::ConsensusDecodable for $thing { + impl ::network::encodable::ConsensusDecodable for $thing { #[inline] - fn consensus_decode(d: &mut D) -> Result<$thing, E> { + fn consensus_decode(d: &mut D) -> Result<$thing, D::Error> { Ok($thing(try!(ConsensusDecodable::consensus_decode(d)))) } } ); } -macro_rules! impl_json { - ($thing:ident, $($field:ident),+) => ( - impl ::serialize::json::ToJson for $thing { - fn to_json(&self) -> ::serialize::json::Json { - use std::collections::BTreeMap; - use serialize::json::{ToJson, Object}; - let mut ret = BTreeMap::new(); - $( ret.insert(stringify!($field).to_string(), self.$field.to_json()); )+ - Object(ret) - } - } - ); -} - macro_rules! impl_array_newtype { ($thing:ident, $ty:ty, $len:expr) => { impl $thing { @@ -201,32 +187,46 @@ macro_rules! impl_array_newtype { macro_rules! impl_array_newtype_encodable { ($thing:ident, $ty:ty, $len:expr) => { - impl, E> ::serialize::Decodable for $thing { - fn decode(d: &mut D) -> Result<$thing, E> { - use serialize::Decodable; - ::assert_type_is_copy::<$ty>(); + impl ::serde::Deserialize for $thing { + fn deserialize(d: &mut D) -> Result<$thing, D::Error> + where D: ::serde::Deserializer + { + // We have to define the Visitor struct inside the function + // to make it local ... what we really need is that it's + // local to the macro, but this is Close Enough. + struct Visitor { + marker: ::std::marker::PhantomData<$thing>, + } + impl ::serde::de::Visitor for Visitor { + type Value = $thing; - d.read_seq(|d, len| { - if len != $len { - Err(d.error("Invalid length")) - } else { + #[inline] + fn visit_seq(&mut self, mut v: V) -> Result<$thing, V::Error> + where V: ::serde::de::SeqVisitor + { unsafe { use std::mem; let mut ret: [$ty; $len] = mem::uninitialized(); - for i in 0..len { - ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); + for i in 0..$len { + ret[i] = try!(v.visit()); } Ok($thing(ret)) } } - }) + } + + // Begin actual function + d.visit(Visitor { marker: ::std::marker::PhantomData }) } } - impl, S> ::serialize::Encodable for $thing { - fn encode(&self, e: &mut E) -> Result<(), S> { - self.as_slice().encode(e) + impl ::serde::Serialize for $thing { + fn serialize(&self, s: &mut S) -> Result<(), S::Error> + where S: ::serde::Serializer + { + let &$thing(ref dat) = self; + (&dat[..]).serialize(s) } } } diff --git a/src/macros.rs b/src/macros.rs index 51a0fd2..38ac77c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -98,17 +98,38 @@ macro_rules! user_enum { } } - impl, E> ::serialize::Encodable for $name { - fn encode(&self, s: &mut S) -> Result<(), E> { - s.emit_str(self.to_string().as_slice()) + impl ::serde::Deserialize for $name { + #[inline] + fn deserialize(d: &mut D) -> Result<$name, D::Error> + where D: ::serde::Deserializer + { + struct Visitor; + impl ::serde::de::Visitor for Visitor { + type Value = $name; + + fn visit_string(&mut self, v: String) -> Result<$name, E> + where E: ::serde::de::Error + { + self.visit_str(&v) + } + + fn visit_str(&mut self, s: &str) -> Result<$name, E> + where E: ::serde::de::Error + { + $( if s == $txt { Ok($name::$elem) } )else* + else { Err(::serde::de::Error::syntax_error()) } + } + } + + d.visit(Visitor) } } - impl , E> ::serialize::Decodable for $name { - fn decode(d: &mut D) -> Result<$name, E> { - let s = try!(d.read_str()); - $( if s.as_slice() == $txt { Ok($name::$elem) } )else* - else { Err(d.error(format!("unknown `{}`", s).as_slice())) } + impl ::serde::Serialize for $name { + fn serialize(&self, s: &mut S) -> Result<(), S::Error> + where S: ::serde::Serializer + { + s.visit_str(&self.to_string()) } } ); diff --git a/src/network/address.rs b/src/network/address.rs index 5fefe4d..a6856aa 100644 --- a/src/network/address.rs +++ b/src/network/address.rs @@ -33,9 +33,9 @@ pub struct Address { pub port: u16 } -impl, E> ConsensusEncodable for Address { +impl ConsensusEncodable for Address { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(self.services.consensus_encode(s)); try!(self.address.consensus_encode(s)); // Explicitly code the port since it needs to be big-endian @@ -45,9 +45,9 @@ impl, E> ConsensusEncodable for Address { } } -impl, E> ConsensusDecodable for Address { +impl ConsensusDecodable for Address { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { Ok(Address { services: try!(ConsensusDecodable::consensus_decode(d)), address: try!(ConsensusDecodable::consensus_decode(d)), diff --git a/src/network/constants.rs b/src/network/constants.rs index 32477c1..ef2b789 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -46,16 +46,16 @@ pub fn magic(network: Network) -> u32 { } } -impl, E> ConsensusEncodable for Network { +impl ConsensusEncodable for Network { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { magic(*self).consensus_encode(s) } } -impl, E> ConsensusDecodable for Network { +impl ConsensusDecodable for Network { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { let magic: u32 = try!(ConsensusDecodable::consensus_decode(d)); match magic { 0xD9B4BEF9 => Ok(Network::Bitcoin), diff --git a/src/network/encodable.rs b/src/network/encodable.rs index ef2dab7..c1809c7 100644 --- a/src/network/encodable.rs +++ b/src/network/encodable.rs @@ -38,15 +38,15 @@ use util::hash::Sha256dHash; use network::serialize::{SimpleDecoder, SimpleEncoder}; /// Data which can be encoded in a consensus-consistent way -pub trait ConsensusEncodable, E> { +pub trait ConsensusEncodable { /// Encode an object with a well-defined format - fn consensus_encode(&self, e: &mut S) -> Result<(), E>; + fn consensus_encode(&self, e: &mut S) -> Result<(), S::Error>; } /// Data which can be encoded in a consensus-consistent way -pub trait ConsensusDecodable, E> { +pub trait ConsensusDecodable { /// Decode an object with a well-defined format - fn consensus_decode(d: &mut D) -> Result; + fn consensus_decode(d: &mut D) -> Result; } /// A variable-length unsigned integer @@ -58,39 +58,39 @@ pub struct VarInt(pub u64); pub struct CheckedData(pub Vec); // Primitive types -impl, E> ConsensusEncodable for u8 { +impl ConsensusEncodable for u8 { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_u8(*self) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u8(*self) } } -impl, E> ConsensusEncodable for u16 { +impl ConsensusEncodable for u16 { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_u16(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u16(self.to_le()) } } -impl, E> ConsensusEncodable for u32 { +impl ConsensusEncodable for u32 { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_u32(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u32(self.to_le()) } } -impl, E> ConsensusEncodable for u64 { +impl ConsensusEncodable for u64 { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_u64(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u64(self.to_le()) } } -impl, E> ConsensusEncodable for i32 { +impl ConsensusEncodable for i32 { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_i32(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i32(self.to_le()) } } -impl, E> ConsensusEncodable for i64 { +impl ConsensusEncodable for i64 { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_i64(self.to_le()) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i64(self.to_le()) } } -impl, E> ConsensusEncodable for VarInt { +impl ConsensusEncodable for VarInt { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { let &VarInt(n) = self; match n { 0...0xFC => { (n as u8).consensus_encode(s) } @@ -101,39 +101,39 @@ impl, E> ConsensusEncodable for VarInt { } } -impl, E> ConsensusDecodable for u8 { +impl ConsensusDecodable for u8 { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_u8() } + fn consensus_decode(d: &mut D) -> Result { d.read_u8() } } -impl, E> ConsensusDecodable for u16 { +impl ConsensusDecodable for u16 { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_u16().map(|n| u16::from_le(n)) } + fn consensus_decode(d: &mut D) -> Result { d.read_u16().map(|n| u16::from_le(n)) } } -impl, E> ConsensusDecodable for u32 { +impl ConsensusDecodable for u32 { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_u32().map(|n| u32::from_le(n)) } + fn consensus_decode(d: &mut D) -> Result { d.read_u32().map(|n| u32::from_le(n)) } } -impl, E> ConsensusDecodable for u64 { +impl ConsensusDecodable for u64 { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_u64().map(|n| u64::from_le(n)) } + fn consensus_decode(d: &mut D) -> Result { d.read_u64().map(|n| u64::from_le(n)) } } -impl, E> ConsensusDecodable for i32 { +impl ConsensusDecodable for i32 { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_i32().map(|n| i32::from_le(n)) } + fn consensus_decode(d: &mut D) -> Result { d.read_i32().map(|n| i32::from_le(n)) } } -impl, E> ConsensusDecodable for i64 { +impl ConsensusDecodable for i64 { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_i64().map(|n| i64::from_le(n)) } + fn consensus_decode(d: &mut D) -> Result { d.read_i64().map(|n| i64::from_le(n)) } } -impl, E> ConsensusDecodable for VarInt { +impl ConsensusDecodable for VarInt { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { let n = try!(d.read_u8()); match n { 0xFF => d.read_u64().map(|n| VarInt(u64::from_le(n))), @@ -145,27 +145,27 @@ impl, E> ConsensusDecodable for VarInt { } // Booleans -impl, E> ConsensusEncodable for bool { +impl ConsensusEncodable for bool { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { s.emit_u8(if *self {1} else {0}) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u8(if *self {1} else {0}) } } -impl, E> ConsensusDecodable for bool { +impl ConsensusDecodable for bool { #[inline] - fn consensus_decode(d: &mut D) -> Result { d.read_u8().map(|n| n != 0) } + fn consensus_decode(d: &mut D) -> Result { d.read_u8().map(|n| n != 0) } } // Strings -impl, E> ConsensusEncodable for String { +impl ConsensusEncodable for String { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { self.as_bytes().consensus_encode(s) } } -impl, E> ConsensusDecodable for String { +impl ConsensusDecodable for String { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { String::from_utf8(try!(ConsensusDecodable::consensus_decode(d))).map_err(|_| d.error("String was not valid UTF8")) } } @@ -174,17 +174,17 @@ impl, E> ConsensusDecodable for String { // Arrays macro_rules! impl_array { ( $size:expr ) => ( - impl, E, T:ConsensusEncodable> ConsensusEncodable for [T; $size] { + impl> ConsensusEncodable for [T; $size] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { for i in self.iter() { try!(i.consensus_encode(s)); } Ok(()) } } - impl, E, T:ConsensusDecodable+Copy> ConsensusDecodable for [T; $size] { + impl + Copy> ConsensusDecodable for [T; $size] { #[inline] - fn consensus_decode(d: &mut D) -> Result<[T; $size], E> { + fn consensus_decode(d: &mut D) -> Result<[T; $size], D::Error> { // Set everything to the first decode let mut ret = [try!(ConsensusDecodable::consensus_decode(d)); $size]; // Set the rest @@ -202,9 +202,9 @@ impl_array!(12); impl_array!(16); impl_array!(32); -impl<'a, S:SimpleEncoder, E, T:ConsensusEncodable> ConsensusEncodable for &'a [T] { +impl<'a, S: SimpleEncoder, T: ConsensusEncodable> ConsensusEncodable for &'a [T] { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(VarInt(self.len() as u64).consensus_encode(s)); for c in self.iter() { try!(c.consensus_encode(s)); } Ok(()) @@ -214,14 +214,14 @@ impl<'a, S:SimpleEncoder, E, T:ConsensusEncodable> ConsensusEncodable, E, T:ConsensusEncodable> ConsensusEncodable for Vec { +impl> ConsensusEncodable for Vec { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { self.as_slice().consensus_encode(s) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { self.as_slice().consensus_encode(s) } } -impl, E, T:ConsensusDecodable> ConsensusDecodable for Vec { +impl> ConsensusDecodable for Vec { #[inline] - fn consensus_decode(d: &mut D) -> Result, E> { + fn consensus_decode(d: &mut D) -> Result, D::Error> { let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d)); let mut ret = Vec::with_capacity(len as usize); for _ in 0..len { ret.push(try!(ConsensusDecodable::consensus_decode(d))); } @@ -229,14 +229,14 @@ impl, E, T:ConsensusDecodable> ConsensusDecodable } } -impl, E, T:ConsensusEncodable> ConsensusEncodable for Box<[T]> { +impl> ConsensusEncodable for Box<[T]> { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { (&self[..]).consensus_encode(s) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { (&self[..]).consensus_encode(s) } } -impl, E, T:ConsensusDecodable> ConsensusDecodable for Box<[T]> { +impl> ConsensusDecodable for Box<[T]> { #[inline] - fn consensus_decode(d: &mut D) -> Result, E> { + fn consensus_decode(d: &mut D) -> Result, D::Error> { let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d)); unsafe { let len = len as usize; @@ -248,9 +248,9 @@ impl, E, T:ConsensusDecodable> ConsensusDecodable } // Options (encoded as vectors of length 0 or 1) -impl, E, T:ConsensusEncodable> ConsensusEncodable for Option { +impl> ConsensusEncodable for Option { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { match *self { Some(ref data) => { try!(1u8.consensus_encode(s)); @@ -262,9 +262,9 @@ impl, E, T:ConsensusEncodable> ConsensusEncodable } } -impl, E, T:ConsensusDecodable> ConsensusDecodable for Option { +impl> ConsensusDecodable for Option { #[inline] - fn consensus_decode(d: &mut D) -> Result, E> { + fn consensus_decode(d: &mut D) -> Result, D::Error> { let bit: u8 = try!(ConsensusDecodable::consensus_decode(d)); Ok(if bit != 0 { Some(try!(ConsensusDecodable::consensus_decode(d))) @@ -282,9 +282,9 @@ fn sha2_checksum(data: &[u8]) -> [u8; 4] { } // Checked data -impl, E> ConsensusEncodable for CheckedData { +impl ConsensusEncodable for CheckedData { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { let &CheckedData(ref data) = self; try!((data.len() as u32).consensus_encode(s)); try!(sha2_checksum(data.as_slice()).consensus_encode(s)); @@ -296,9 +296,9 @@ impl, E> ConsensusEncodable for CheckedData { } } -impl, E> ConsensusDecodable for CheckedData { +impl ConsensusDecodable for CheckedData { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { let len: u32 = try!(ConsensusDecodable::consensus_decode(d)); let checksum: [u8; 4] = try!(ConsensusDecodable::consensus_decode(d)); let mut ret = Vec::with_capacity(len as usize); @@ -315,53 +315,53 @@ impl, E> ConsensusDecodable for CheckedData { // Tuples macro_rules! tuple_encode { ($($x:ident),*) => ( - impl , EE, $($x: ConsensusEncodable),*> ConsensusEncodable for ($($x),*) { + impl ),*> ConsensusEncodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_encode(&self, s: &mut SS) -> Result<(), EE> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { let &($(ref $x),*) = self; $( try!($x.consensus_encode(s)); )* Ok(()) } } - impl, EE, $($x: ConsensusDecodable),*> ConsensusDecodable for ($($x),*) { + impl),*> ConsensusDecodable for ($($x),*) { #[inline] #[allow(non_snake_case)] - fn consensus_decode(d: &mut DD) -> Result<($($x),*), EE> { + fn consensus_decode(d: &mut D) -> Result<($($x),*), D::Error> { Ok(($(try!({let $x = ConsensusDecodable::consensus_decode(d); $x })),*)) } } ); } -tuple_encode!(A, B); -tuple_encode!(A, B, C, D); -tuple_encode!(A, B, C, D, E, F); -tuple_encode!(A, B, C, D, E, F, G, H); - +tuple_encode!(T0, T1); +tuple_encode!(T0, T1, T2, T3); +tuple_encode!(T0, T1, T2, T3, T4, T5); +tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); // References -impl, E, T: ConsensusEncodable> ConsensusEncodable for Box { +impl> ConsensusEncodable for Box { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { (**self).consensus_encode(s) } + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { (**self).consensus_encode(s) } } -impl, E, T: ConsensusDecodable> ConsensusDecodable for Box { +impl> ConsensusDecodable for Box { #[inline] - fn consensus_decode(d: &mut D) -> Result, E> { + fn consensus_decode(d: &mut D) -> Result, D::Error> { ConsensusDecodable::consensus_decode(d).map(|res| Box::new(res)) } } - // HashMap -impl, E, T, - K:ConsensusEncodable+Eq+Hash, - V:ConsensusEncodable, - H:Hasher+Default> ConsensusEncodable for HashMap { +impl ConsensusEncodable for HashMap + where S: SimpleEncoder, + H: Hasher + Default, + K: ConsensusEncodable + Eq + Hash, + V: ConsensusEncodable +{ #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(VarInt(self.len() as u64).consensus_encode(s)); for (key, value) in self.iter() { try!(key.consensus_encode(s)); @@ -371,12 +371,14 @@ impl, E, T, } } -impl, E, T, - K:ConsensusDecodable+Eq+Hash, - V:ConsensusDecodable, - H:Hasher+Default> ConsensusDecodable for HashMap { +impl ConsensusDecodable for HashMap + where D: SimpleDecoder, + H: Hasher + Default, + K: ConsensusDecodable + Eq + Hash, + V: ConsensusDecodable +{ #[inline] - fn consensus_decode(d: &mut D) -> Result, E> { + fn consensus_decode(d: &mut D) -> Result, D::Error> { let VarInt(len): VarInt = try!(ConsensusDecodable::consensus_decode(d)); let mut ret = HashMap::with_capacity_and_hasher(len as usize, Default::default()); diff --git a/src/network/message.rs b/src/network/message.rs index 0272cb1..5cf74ca 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -38,9 +38,9 @@ use util::misc::prepend_err; #[derive(PartialEq, Eq, Clone, Debug)] pub struct CommandString(pub String); -impl, E> ConsensusEncodable for CommandString { +impl ConsensusEncodable for CommandString { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { let &CommandString(ref inner_str) = self; let mut rawbytes = [0u8; 12]; rawbytes.clone_from_slice(inner_str.as_bytes().as_slice()); @@ -48,9 +48,9 @@ impl, E> ConsensusEncodable for CommandString { } } -impl, E> ConsensusDecodable for CommandString { +impl ConsensusDecodable for CommandString { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { let rawbytes: [u8; 12] = try!(ConsensusDecodable::consensus_decode(d)); let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None })); Ok(CommandString(rv)) @@ -133,8 +133,8 @@ impl RawNetworkMessage { } } -impl, E> ConsensusEncodable for RawNetworkMessage { - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { +impl ConsensusEncodable for RawNetworkMessage { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(self.magic.consensus_encode(s)); try!(CommandString(self.command()).consensus_encode(s)); try!(CheckedData(match self.payload { @@ -156,7 +156,7 @@ impl, E> ConsensusEncodable for RawNetworkMessage { } } -impl> ConsensusDecodable for RawNetworkMessage { +impl> ConsensusDecodable for RawNetworkMessage { fn consensus_decode(d: &mut D) -> io::Result { let magic = try!(ConsensusDecodable::consensus_decode(d)); let CommandString(cmd): CommandString= try!(ConsensusDecodable::consensus_decode(d)); diff --git a/src/network/message_blockdata.rs b/src/network/message_blockdata.rs index 9326560..9c296a9 100644 --- a/src/network/message_blockdata.rs +++ b/src/network/message_blockdata.rs @@ -97,9 +97,9 @@ impl GetHeadersMessage { impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); -impl, E> ConsensusEncodable for Inventory { +impl ConsensusEncodable for Inventory { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { try!(match self.inv_type { InvType::Error => 0u32, InvType::Transaction => 1, @@ -109,9 +109,9 @@ impl, E> ConsensusEncodable for Inventory { } } -impl, E> ConsensusDecodable for Inventory { +impl ConsensusDecodable for Inventory { #[inline] - fn consensus_decode(d: &mut D) -> Result { + fn consensus_decode(d: &mut D) -> Result { let int_type: u32 = try!(ConsensusDecodable::consensus_decode(d)); Ok(Inventory { inv_type: match int_type { diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 0816e37..b4371cd 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -18,7 +18,7 @@ //! capabilities //! -use std::io::Result; +use std::io; use network::constants; use network::address::Address; @@ -54,7 +54,7 @@ pub struct VersionMessage { impl VersionMessage { // TODO: we have fixed services and relay to 0 /// Constructs a new `version` message - pub fn new(timestamp: i64, mut socket: Socket, nonce: u64, start_height: i32) -> Result { + pub fn new(timestamp: i64, mut socket: Socket, nonce: u64, start_height: i32) -> io::Result { let recv_addr = socket.receiver_address(); let send_addr = socket.sender_address(); // If we are not connected, we might not be able to get these address.s @@ -88,7 +88,7 @@ impl_consensus_encoding!(VersionMessage, version, services, timestamp, mod tests { use super::VersionMessage; - use std::io::Result; + use std::io; use serialize::hex::FromHex; use network::serialize::{deserialize, serialize}; @@ -98,7 +98,7 @@ mod tests { // This message is from my satoshi node, morning of May 27 2014 let from_sat = "721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001".from_hex().unwrap(); - let decode: Result = deserialize(from_sat.clone()); + let decode: io::Result = deserialize(from_sat.clone()); assert!(decode.is_ok()); let real_decode = decode.unwrap(); assert_eq!(real_decode.version, 70002); diff --git a/src/network/serialize.rs b/src/network/serialize.rs index 9f00555..6bd4f5d 100644 --- a/src/network/serialize.rs +++ b/src/network/serialize.rs @@ -39,20 +39,20 @@ impl BitcoinHash for Vec { } /// Encode an object into a vector -pub fn serialize, io::Error>>(obj: &T) -> io::Result> { +pub fn serialize>>>>(obj: &T) -> io::Result> { let mut encoder = RawEncoder::new(Cursor::new(vec![])); try!(obj.consensus_encode(&mut encoder)); Ok(encoder.unwrap().unwrap()) } /// Encode an object into a hex-encoded string -pub fn serialize_hex, io::Error>>(obj: &T) -> io::Result { +pub fn serialize_hex>>>>(obj: &T) -> io::Result { let serial = try!(serialize(obj)); Ok(serial.as_slice().to_hex()) } /// Deserialize an object from a vector -pub fn deserialize, io::Error>>(data: Vec) -> io::Result { +pub fn deserialize>>>>(data: Vec) -> io::Result { let mut decoder = RawDecoder::new(Cursor::new(data)); ConsensusDecodable::consensus_decode(&mut decoder) } @@ -92,59 +92,65 @@ impl RawDecoder { } /// A simple Encoder trait -pub trait SimpleEncoder { +pub trait SimpleEncoder { + type Error; + /// Output a 64-bit uint - fn emit_u64(&mut self, v: u64) -> Result<(), E>; + fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; /// Output a 32-bit uint - fn emit_u32(&mut self, v: u32) -> Result<(), E>; + fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; /// Output a 16-bit uint - fn emit_u16(&mut self, v: u16) -> Result<(), E>; + fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; /// Output a 8-bit uint - fn emit_u8(&mut self, v: u8) -> Result<(), E>; + fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; /// Output a 64-bit int - fn emit_i64(&mut self, v: i64) -> Result<(), E>; + fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; /// Output a 32-bit int - fn emit_i32(&mut self, v: i32) -> Result<(), E>; + fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; /// Output a 16-bit int - fn emit_i16(&mut self, v: i16) -> Result<(), E>; + fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; /// Output a 8-bit int - fn emit_i8(&mut self, v: i8) -> Result<(), E>; + fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>; /// Output a boolean - fn emit_bool(&mut self, v: bool) -> Result<(), E>; + fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>; } /// A simple Decoder trait -pub trait SimpleDecoder { +pub trait SimpleDecoder { + type Error; + /// Read a 64-bit uint - fn read_u64(&mut self) -> Result; + fn read_u64(&mut self) -> Result; /// Read a 32-bit uint - fn read_u32(&mut self) -> Result; + fn read_u32(&mut self) -> Result; /// Read a 16-bit uint - fn read_u16(&mut self) -> Result; + fn read_u16(&mut self) -> Result; /// Read a 8-bit uint - fn read_u8(&mut self) -> Result; + fn read_u8(&mut self) -> Result; /// Read a 64-bit int - fn read_i64(&mut self) -> Result; + fn read_i64(&mut self) -> Result; /// Read a 32-bit int - fn read_i32(&mut self) -> Result; + fn read_i32(&mut self) -> Result; /// Read a 16-bit int - fn read_i16(&mut self) -> Result; + fn read_i16(&mut self) -> Result; /// Read a 8-bit int - fn read_i8(&mut self) -> Result; + fn read_i8(&mut self) -> Result; /// Read a boolean - fn read_bool(&mut self) -> Result; + fn read_bool(&mut self) -> Result; /// Signal a decoding error - fn error(&mut self, err: &str) -> E; + fn error(&mut self, err: &str) -> Self::Error; } // TODO: trait reform: impl SimpleEncoder for every Encoder, ditto for Decoder -impl SimpleEncoder for RawEncoder { +impl SimpleEncoder for RawEncoder { + type Error = io::Error; + #[inline] fn emit_u64(&mut self, v: u64) -> io::Result<()> { self.writer.write_le_u64(v) } #[inline] @@ -167,7 +173,9 @@ impl SimpleEncoder for RawEncoder { fn emit_bool(&mut self, v: bool) -> io::Result<()> { self.writer.write_i8(if v {1} else {0}) } } -impl SimpleDecoder for RawDecoder { +impl SimpleDecoder for RawDecoder { + type Error = io::Error; + #[inline] fn read_u64(&mut self) -> io::Result { self.reader.read_le_u64() } #[inline] diff --git a/src/util/base58.rs b/src/util/base58.rs index 8765d0c..1b98c83 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -16,7 +16,7 @@ use byteorder::{ByteOrder, LittleEndian}; -use std::string; +use std::str; use util::hash::Sha256dHash; @@ -132,7 +132,7 @@ pub fn base58_encode_slice(data: &[u8]) -> String { // Unsafely translate the bytes to a utf8 string unsafe { // Copy leading zeroes directly - let mut ret = string::raw::from_utf8(data.iter().take_while(|&&x| x == 0) + let mut ret = str::from_utf8(data.iter().take_while(|&&x| x == 0) .map(|_| BASE58_CHARS[0]) .collect()); // Copy rest of string diff --git a/src/util/error.rs b/src/util/error.rs index 56283cc..ad2149b 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -18,9 +18,6 @@ use std::io; -/// A success/failure return value -pub type Result = Result; - /// A general error code #[derive(PartialEq, Eq, Debug, Clone)] pub enum Error { diff --git a/src/util/hash.rs b/src/util/hash.rs index 3721fa7..35a0982 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -22,7 +22,7 @@ use std::fmt; use std::io::Cursor; use std::mem::transmute; use std::hash; -use serialize::json::{self, ToJson}; +use serde; use byteorder::{ByteOrder, LittleEndian}; use crypto::digest::Digest; @@ -160,37 +160,48 @@ impl Sha256dHash { // used only for user-facing stuff. Internal and network serialization is // little-endian and should be done using the consensus `encodable::ConsensusEncodable` // interface. -impl ToJson for Sha256dHash { - #[inline] - fn to_json(&self) -> json::Json { - json::String(self.be_hex_string()) +impl serde::Serialize for Sha256dHash { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer, + { + serializer.visit_str(&self.be_hex_string()) } } -// Non-consensus encoding (big-endian hex string) -impl, E> ::serialize::Encodable for Sha256dHash { +impl serde::Deserialize for Sha256dHash { #[inline] - fn encode(&self, s: &mut S) -> Result<(), E> { - s.emit_str(self.be_hex_string().as_slice()) - } -} - -impl, E> ::serialize::Decodable for Sha256dHash { - #[inline] - fn decode(d: &mut D) -> Result { + fn deserialize(d: &mut D) -> Result + where D: serde::Deserializer + { use serialize::hex::FromHex; - let hex_str = try!(d.read_str()); - if hex_str.len() != 64 { - d.error("incorrect hash length"); + struct Sha256dHashVisitor; + impl serde::de::Visitor for Sha256dHashVisitor { + type Value = Sha256dHash; + + fn visit_string(&mut self, v: String) -> Result + where E: serde::de::Error + { + self.visit_str(&v) + } + + fn visit_str(&mut self, hex_str: &str) -> Result + where E: serde::de::Error + { + if hex_str.len() != 64 { + return Err(serde::de::Error::syntax_error()); + } + let raw_str = try!(hex_str.as_slice().from_hex() + .map_err(|_| serde::de::Error::syntax_error())); + let mut ret = [0u8; 32]; + for i in 0..32 { + ret[i] = raw_str[31 - i]; + } + Ok(Sha256dHash(ret)) + } } - let raw_str = try!(hex_str.as_slice().from_hex() - .map_err(|_| d.error("non-hexadecimal hash string"))); - let mut ret = [0u8; 32]; - for i in 0..32 { - ret[i] = raw_str[31 - i]; - } - Ok(Sha256dHash(ret)) + + d.visit(Sha256dHashVisitor) } } diff --git a/src/util/iter.rs b/src/util/iter.rs index d7a83a3..6972613 100644 --- a/src/util/iter.rs +++ b/src/util/iter.rs @@ -18,14 +18,18 @@ //! standard library. /// An iterator that returns pairs of elements -pub struct Pair { +pub struct Pair + where I: Iterator +{ iter: I, - last_elem: Option + last_elem: Option } -impl> Iterator<(A, A)> for Pair { +impl Iterator for Pair { + type Item = (I::Item, I::Item); + #[inline] - fn next(&mut self) -> Option<(A, A)> { + fn next(&mut self) -> Option<(I::Item, I::Item)> { let elem1 = self.iter.next(); if elem1.is_none() { None @@ -49,28 +53,28 @@ impl> Iterator<(A, A)> for Pair { } } -impl> Pair { +impl Pair { /// Returns the last element of the iterator if there were an odd /// number of elements remaining before it was Pair-ified. #[inline] - pub fn remainder(self) -> Option { + pub fn remainder(self) -> Option { self.last_elem } } /// Returns an iterator that returns elements of the original iterator 2 at a time -pub trait Pairable { +pub trait Pairable { /// Returns an iterator that returns elements of the original iterator 2 at a time - fn pair(self) -> Pair; + fn pair(self) -> Pair; } -impl> Pairable for I { +impl Pairable for I { /// Creates an iterator that yields pairs ef elements from the underlying /// iterator, yielding `None` when there are fewer than two elements to /// return. #[inline] - fn pair(self) -> Pair { - Pair{iter: self, last_elem: None} + fn pair(self) -> Pair { + Pair {iter: self, last_elem: None } } } diff --git a/src/util/patricia_tree.rs b/src/util/patricia_tree.rs index 12fd4e2..3791a63 100644 --- a/src/util/patricia_tree.rs +++ b/src/util/patricia_tree.rs @@ -38,7 +38,9 @@ pub struct PatriciaTree { skip_len: u8 } -impl+ops::Shl+ops::Shr, V> PatriciaTree { +impl PatriciaTree + where K: BitArray + cmp::Eq + Zero + One + ops::BitXor + ops::Shl + ops::Shr +{ /// Constructs a new Patricia tree pub fn new() -> PatriciaTree { PatriciaTree { @@ -214,7 +216,9 @@ impl+ops::Shl+ops::Shr Option { /// Return value is (deletable, actual return value), where `deletable` is true /// is true when the entire node can be deleted (i.e. it has no children) - fn recurse+ops::Shr+ops::Shl, V>(tree: &mut PatriciaTree, key: &K, key_len: usize) -> (bool, Option) { + fn recurse(tree: &mut PatriciaTree, key: &K, key_len: usize) -> (bool, Option) + where K: BitArray + cmp::Eq + Zero + One + ops::Add + ops::Shr + ops::Shl + { // If the search key is shorter than the node prefix, there is no // way we can match, so fail. if key_len < tree.skip_len as usize { @@ -386,8 +390,12 @@ impl PatriciaTree { } } -impl, E, K:ConsensusEncodable, V:ConsensusEncodable> ConsensusEncodable for PatriciaTree { - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { +impl ConsensusEncodable for PatriciaTree + where S: SimpleEncoder, + K: ConsensusEncodable, + V: ConsensusEncodable +{ + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { // Depth-first serialization: serialize self, then children try!(self.skip_prefix.consensus_encode(s)); try!(self.skip_len.consensus_encode(s)); @@ -398,8 +406,12 @@ impl, E, K:ConsensusEncodable, V:ConsensusEncodable, E, K:ConsensusDecodable, V:ConsensusDecodable> ConsensusDecodable for PatriciaTree { - fn consensus_decode(d: &mut D) -> Result, E> { +impl ConsensusDecodable for PatriciaTree + where D: SimpleDecoder, + K: ConsensusDecodable, + V: ConsensusDecodable +{ + fn consensus_decode(d: &mut D) -> Result, D::Error> { Ok(PatriciaTree { skip_prefix: try!(ConsensusDecodable::consensus_decode(d)), skip_len: try!(ConsensusDecodable::consensus_decode(d)), @@ -425,7 +437,9 @@ pub struct MutItems<'tree, K, V> { marker: marker::PhantomData<&'tree PatriciaTree> } -impl<'a, K, V> Iterator<&'a V> for Items<'a, K, V> { +impl<'a, K, V> Iterator for Items<'a, K, V> { + type Item = &'a V; + fn next(&mut self) -> Option<&'a V> { fn borrow_opt<'a, K, V>(opt_ptr: &'a Option>>) -> Option<&'a PatriciaTree> { opt_ptr.as_ref().map(|b| &**b) @@ -469,7 +483,9 @@ impl<'a, K, V> Iterator<&'a V> for Items<'a, K, V> { } } -impl<'a, K, V> Iterator<&'a mut V> for MutItems<'a, K, V> { +impl<'a, K, V> Iterator for MutItems<'a, K, V> { + type Item = &'a mut V; + fn next(&mut self) -> Option<&'a mut V> { fn borrow_opt<'a, K, V>(opt_ptr: &'a Option>>) -> *mut PatriciaTree { match *opt_ptr { diff --git a/src/util/uint.rs b/src/util/uint.rs index 7003a9a..792001e 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -90,7 +90,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::Add<$name,$name> for $name { + impl ::std::ops::Add<$name> for $name { + type Output = $name; + fn add(&self, other: &$name) -> $name { let &$name(ref me) = self; let &$name(ref you) = other; @@ -108,14 +110,18 @@ macro_rules! construct_uint { } } - impl ::std::ops::Sub<$name,$name> for $name { + impl ::std::ops::Sub<$name> for $name { + type Output = $name; + #[inline] fn sub(&self, other: &$name) -> $name { *self + !*other + One::one() } } - impl ::std::ops::Mul<$name,$name> for $name { + impl ::std::ops::Mul<$name> for $name { + type Output = $name; + fn mul(&self, other: &$name) -> $name { let mut me = *self; // TODO: be more efficient about this @@ -126,7 +132,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::Div<$name,$name> for $name { + impl ::std::ops::Div<$name> for $name { + type Output = $name; + fn div(&self, other: &$name) -> $name { let mut sub_copy = *self; let mut shift_copy = *other; @@ -197,7 +205,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::BitAnd<$name,$name> for $name { + impl ::std::ops::BitAnd<$name> for $name { + type Output = $name; + #[inline] fn bitand(&self, other: &$name) -> $name { let &$name(ref arr1) = self; @@ -210,7 +220,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::BitXor<$name,$name> for $name { + impl ::std::ops::BitXor<$name> for $name { + type Output = $name; + #[inline] fn bitxor(&self, other: &$name) -> $name { let &$name(ref arr1) = self; @@ -223,7 +235,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::BitOr<$name,$name> for $name { + impl ::std::ops::BitOr<$name> for $name { + type Output = $name; + #[inline] fn bitor(&self, other: &$name) -> $name { let &$name(ref arr1) = self; @@ -236,7 +250,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::Not<$name> for $name { + impl ::std::ops::Not for $name { + type Output = $name; + #[inline] fn not(&self) -> $name { let &$name(ref arr) = self; @@ -248,7 +264,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::Shl for $name { + impl ::std::ops::Shl for $name { + type Output = $name; + fn shl(&self, shift: &usize) -> $name { let &$name(ref original) = self; let mut ret = [0u64; $n_words]; @@ -268,7 +286,9 @@ macro_rules! construct_uint { } } - impl ::std::ops::Shr for $name { + impl ::std::ops::Shr for $name { + type Output = $name; + #[allow(unsigned_negate)] fn shr(&self, shift: &usize) -> $name { let &$name(ref original) = self; @@ -316,9 +336,9 @@ macro_rules! construct_uint { } } - impl, E> ::network::encodable::ConsensusEncodable for $name { + impl ::network::encodable::ConsensusEncodable for $name { #[inline] - fn consensus_encode(&self, s: &mut S) -> Result<(), E> { + fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { use network::encodable::ConsensusEncodable; let &$name(ref data) = self; for word in data.iter() { try!(word.consensus_encode(s)); } @@ -326,8 +346,8 @@ macro_rules! construct_uint { } } - impl, E> ::network::encodable::ConsensusDecodable for $name { - fn consensus_decode(d: &mut D) -> Result<$name, E> { + impl ::network::encodable::ConsensusDecodable for $name { + fn consensus_decode(d: &mut D) -> Result<$name, D::Error> { use network::encodable::ConsensusDecodable; let ret: [u64; $n_words] = try!(ConsensusDecodable::consensus_decode(d)); Ok($name(ret))