Add a bunch of small hashtypes for cheap'n'collidey hashtables
This commit is contained in:
parent
1522ab841d
commit
611b1f57c9
|
@ -34,7 +34,7 @@ use network::encodable::ConsensusEncodable;
|
||||||
use network::serialize::BitcoinHash;
|
use network::serialize::BitcoinHash;
|
||||||
|
|
||||||
/// A transaction input, which defines old coins to be consumed
|
/// A transaction input, which defines old coins to be consumed
|
||||||
#[deriving(Clone, PartialEq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct TxIn {
|
pub struct TxIn {
|
||||||
/// The hash of the transaction whose output is being used an an input
|
/// The hash of the transaction whose output is being used an an input
|
||||||
pub prev_hash: Sha256dHash,
|
pub prev_hash: Sha256dHash,
|
||||||
|
@ -51,7 +51,7 @@ pub struct TxIn {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A transaction output, which defines new coins to be created from old ones.
|
/// A transaction output, which defines new coins to be created from old ones.
|
||||||
#[deriving(Clone, PartialEq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct TxOut {
|
pub struct TxOut {
|
||||||
/// The value of the output, in satoshis
|
/// The value of the output, in satoshis
|
||||||
pub value: u64,
|
pub value: u64,
|
||||||
|
@ -67,7 +67,7 @@ impl Default for TxOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Bitcoin transaction, which describes an authenticated movement of coins
|
/// A Bitcoin transaction, which describes an authenticated movement of coins
|
||||||
#[deriving(Clone, PartialEq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct Transaction {
|
pub struct Transaction {
|
||||||
/// The protocol version, should always be 1.
|
/// The protocol version, should always be 1.
|
||||||
pub version: u32,
|
pub version: u32,
|
||||||
|
|
|
@ -36,6 +36,25 @@ macro_rules! impl_consensus_encoding(
|
||||||
);
|
);
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro_rules! impl_newtype_consensus_encoding(
|
||||||
|
($thing:ident) => (
|
||||||
|
impl<S: ::network::serialize::SimpleEncoder<E>, E> ::network::encodable::ConsensusEncodable<S, E> for $thing {
|
||||||
|
#[inline]
|
||||||
|
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
||||||
|
let &$thing(ref data) = self;
|
||||||
|
data.consensus_encode(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: ::network::serialize::SimpleDecoder<E>, E> ::network::encodable::ConsensusDecodable<D, E> for $thing {
|
||||||
|
#[inline]
|
||||||
|
fn consensus_decode(d: &mut D) -> Result<$thing, E> {
|
||||||
|
Ok($thing(try!(ConsensusDecodable::consensus_decode(d))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
)
|
||||||
|
|
||||||
macro_rules! impl_json(
|
macro_rules! impl_json(
|
||||||
($thing:ident, $($field:ident),+) => (
|
($thing:ident, $($field:ident),+) => (
|
||||||
impl ::serialize::json::ToJson for $thing {
|
impl ::serialize::json::ToJson for $thing {
|
||||||
|
|
|
@ -319,23 +319,33 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for CheckedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tuples
|
// Tuples
|
||||||
impl<S:SimpleEncoder<E>, E, T: ConsensusEncodable<S, E>, U: ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for (T, U) {
|
macro_rules! tuple_encode(
|
||||||
|
($($x:ident),*) => (
|
||||||
|
impl <SS:SimpleEncoder<EE>, EE, $($x: ConsensusEncodable<SS, EE>),*> ConsensusEncodable<SS, EE> for ($($x),*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
#[allow(uppercase_variables)]
|
||||||
let &(ref s1, ref s2) = self;
|
fn consensus_encode(&self, s: &mut SS) -> Result<(), EE> {
|
||||||
try!(s1.consensus_encode(s));
|
let &($(ref $x),*) = self;
|
||||||
try!(s2.consensus_encode(s));
|
$( try!($x.consensus_encode(s)); )*
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<D:SimpleDecoder<E>, E, T: ConsensusDecodable<D, E>, U: ConsensusDecodable<D, E>> ConsensusDecodable<D, E> for (T, U) {
|
|
||||||
#[inline]
|
|
||||||
fn consensus_decode(d: &mut D) -> Result<(T, U), E> {
|
|
||||||
Ok((try!(ConsensusDecodable::consensus_decode(d)),
|
|
||||||
try!(ConsensusDecodable::consensus_decode(d))))
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
impl<DD:SimpleDecoder<EE>, EE, $($x: ConsensusDecodable<DD, EE>),*> ConsensusDecodable<DD, EE> for ($($x),*) {
|
||||||
|
#[inline]
|
||||||
|
#[allow(uppercase_variables)]
|
||||||
|
fn consensus_decode(d: &mut DD) -> Result<($($x),*), EE> {
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
// References
|
// References
|
||||||
impl<S:SimpleEncoder<E>, E, T: ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for Box<T> {
|
impl<S:SimpleEncoder<E>, E, T: ConsensusEncodable<S, E>> ConsensusEncodable<S, E> for Box<T> {
|
||||||
|
|
|
@ -28,7 +28,7 @@ use crypto::digest::Digest;
|
||||||
use crypto::sha2;
|
use crypto::sha2;
|
||||||
|
|
||||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder, SimpleEncoder};
|
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder};
|
||||||
use util::uint::Uint128;
|
use util::uint::Uint128;
|
||||||
use util::uint::Uint256;
|
use util::uint::Uint256;
|
||||||
|
|
||||||
|
@ -44,6 +44,19 @@ pub struct Ripemd160Hash([u8, ..20]);
|
||||||
/// A "hasher" which just truncates
|
/// A "hasher" which just truncates
|
||||||
pub struct DumbHasher;
|
pub struct DumbHasher;
|
||||||
|
|
||||||
|
/// A 32-bit hash obtained by truncating a real hash
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
|
pub struct Hash32((u8, u8, u8, u8));
|
||||||
|
|
||||||
|
/// A 48-bit hash obtained by truncating a real hash
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
|
pub struct Hash48((u8, u8, u8, u8, u8, u8));
|
||||||
|
|
||||||
|
/// A 64-bit hash obtained by truncating a real hash
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
|
pub struct Hash64((u8, u8, u8, u8, u8, u8, u8, u8));
|
||||||
|
|
||||||
|
|
||||||
// Allow these to be used as a key for Rust's HashMap et. al.
|
// Allow these to be used as a key for Rust's HashMap et. al.
|
||||||
impl hash::Hash<u64> for Sha256dHash {
|
impl hash::Hash<u64> for Sha256dHash {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -72,6 +85,32 @@ impl hash::Hash<u64> for Uint128 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl hash::Hash<u64> for Hash32 {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut u64) {
|
||||||
|
let &Hash32((a, b, c, d)) = self;
|
||||||
|
*state = a as u64 + (b as u64 << 8) + (c as u64 << 16) + (d as u64 << 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl hash::Hash<u64> for Hash48 {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut u64) {
|
||||||
|
let &Hash48((a, b, c, d, e, f)) = self;
|
||||||
|
*state = a as u64 + (b as u64 << 8) + (c as u64 << 16) + (d as u64 << 24) +
|
||||||
|
(e as u64 << 32) + (f as u64 << 40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl hash::Hash<u64> for Hash64 {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut u64) {
|
||||||
|
let &Hash64((a, b, c, d, e, f, g, h)) = self;
|
||||||
|
*state = a as u64 + (b as u64 << 8) + (c as u64 << 16) + (d as u64 << 24) +
|
||||||
|
(e as u64 << 32) + (f as u64 << 40) + (g as u64 << 48) + (h as u64 << 56);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl hash::Hasher<u64> for DumbHasher {
|
impl hash::Hasher<u64> for DumbHasher {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<T: hash::Hash<u64>>(&self, value: &T) -> u64 {
|
fn hash<T: hash::Hash<u64>>(&self, value: &T) -> u64 {
|
||||||
|
@ -122,6 +161,30 @@ impl Sha256dHash {
|
||||||
data[31]])) }
|
data[31]])) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a hash to a Hash32 by truncation
|
||||||
|
#[inline]
|
||||||
|
pub fn into_hash32(self) -> Hash32 {
|
||||||
|
let Sha256dHash(data) = self;
|
||||||
|
unsafe { transmute([data[0], data[8], data[16], data[24]]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a hash to a Hash48 by truncation
|
||||||
|
#[inline]
|
||||||
|
pub fn into_hash48(self) -> Hash48 {
|
||||||
|
let Sha256dHash(data) = self;
|
||||||
|
unsafe { transmute([data[0], data[6], data[12], data[18], data[24], data[30]]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Human-readable hex output
|
||||||
|
|
||||||
|
/// Converts a hash to a Hash64 by truncation
|
||||||
|
#[inline]
|
||||||
|
pub fn into_hash64(self) -> Hash64 {
|
||||||
|
let Sha256dHash(data) = self;
|
||||||
|
unsafe { transmute([data[0], data[4], data[8], data[12],
|
||||||
|
data[16], data[20], data[24], data[28]]) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Human-readable hex output
|
/// Human-readable hex output
|
||||||
pub fn le_hex_string(&self) -> String {
|
pub fn le_hex_string(&self) -> String {
|
||||||
let &Sha256dHash(data) = self;
|
let &Sha256dHash(data) = self;
|
||||||
|
@ -214,19 +277,10 @@ impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for Sha256dHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consensus encoding (little-endian)
|
// Consensus encoding (little-endian)
|
||||||
impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Sha256dHash {
|
impl_newtype_consensus_encoding!(Hash32)
|
||||||
#[inline]
|
impl_newtype_consensus_encoding!(Hash48)
|
||||||
fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
|
impl_newtype_consensus_encoding!(Hash64)
|
||||||
self.into_uint256().consensus_encode(s)
|
impl_newtype_consensus_encoding!(Sha256dHash)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Sha256dHash {
|
|
||||||
#[inline]
|
|
||||||
fn consensus_decode(d: &mut D) -> Result<Sha256dHash, E> {
|
|
||||||
Ok(Sha256dHash(try!(ConsensusDecodable::consensus_decode(d))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::LowerHex for Sha256dHash {
|
impl fmt::LowerHex for Sha256dHash {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
Loading…
Reference in New Issue