#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![deny(missing_docs)]
#![allow(bare_trait_objects)]
#![allow(ellipsis_inclusive_range_patterns)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#[cfg(all(test, feature = "unstable"))] extern crate test;
#[cfg(any(test, feature="std"))] pub extern crate core;
#[cfg(feature="serde")] pub extern crate serde;
#[cfg(all(test,feature="serde"))] extern crate serde_test;
#[macro_use] mod util;
#[macro_use] mod serde_macros;
#[cfg(any(test, feature = "std"))] mod std_impls;
pub mod error;
pub mod hex;
pub mod hash160;
pub mod hmac;
pub mod ripemd160;
pub mod sha1;
pub mod sha256;
pub mod sha512;
pub mod sha256d;
pub mod siphash24;
pub mod cmp;
use core::{borrow, fmt, hash, ops};
pub use hmac::{Hmac, HmacEngine};
pub use error::Error;
pub trait HashEngine: Clone + Default {
type MidState;
fn midstate(&self) -> Self::MidState;
const BLOCK_SIZE: usize;
fn input(&mut self, data: &[u8]);
}
pub trait Hash: Copy + Clone + PartialEq + Eq + Default + PartialOrd + Ord +
hash::Hash + fmt::Debug + fmt::Display + fmt::LowerHex +
ops::Index<ops::RangeFull, Output = [u8]> +
ops::Index<ops::RangeFrom<usize>, Output = [u8]> +
ops::Index<ops::RangeTo<usize>, Output = [u8]> +
ops::Index<ops::Range<usize>, Output = [u8]> +
ops::Index<usize, Output = u8> +
borrow::Borrow<[u8]>
{
type Engine: HashEngine;
type Inner: hex::FromHex;
fn engine() -> Self::Engine {
Self::Engine::default()
}
fn from_engine(e: Self::Engine) -> Self;
const LEN: usize;
fn from_slice(sl: &[u8]) -> Result<Self, Error>;
fn hash(data: &[u8]) -> Self {
let mut engine = Self::engine();
engine.input(data);
Self::from_engine(engine)
}
const DISPLAY_BACKWARD: bool = false;
fn into_inner(self) -> Self::Inner;
fn from_inner(inner: Self::Inner) -> Self;
}
#[macro_export]
macro_rules! hash_newtype {
($newtype:ident, $hash:ty, $len:expr, $docs:meta) => {
#[$docs]
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
pub struct $newtype($hash);
hex_fmt_impl!(Debug, $newtype);
hex_fmt_impl!(Display, $newtype);
hex_fmt_impl!(LowerHex, $newtype);
index_impl!($newtype);
serde_impl!($newtype, $len);
borrow_slice_impl!($newtype);
impl $newtype {
pub fn as_hash(&self) -> $hash {
self.0
}
}
impl ::std::convert::From<$hash> for $newtype {
fn from(inner: $hash) -> $newtype {
Self { 0: inner }
}
}
impl ::std::convert::From<$newtype> for $hash {
fn from(hashtype: $newtype) -> $hash {
hashtype.0
}
}
impl $crate::Hash for $newtype {
type Engine = <$hash as $crate::Hash>::Engine;
type Inner = <$hash as $crate::Hash>::Inner;
const LEN: usize = <$hash as $crate::Hash>::LEN;
const DISPLAY_BACKWARD: bool = <$hash as $crate::Hash>::DISPLAY_BACKWARD;
fn from_engine(e: Self::Engine) -> Self {
Self::from(<$hash as $crate::Hash>::from_engine(e))
}
#[inline]
fn from_slice(sl: &[u8]) -> Result<$newtype, $crate::Error> {
Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?))
}
#[inline]
fn from_inner(inner: Self::Inner) -> Self {
$newtype(<$hash as $crate::Hash>::from_inner(inner))
}
#[inline]
fn into_inner(self) -> Self::Inner {
self.0.into_inner()
}
}
};
}
#[cfg(test)]
mod test {
use Hash;
hash_newtype!(TestNewtype, ::sha256d::Hash, 32, doc="A test newtype");
hash_newtype!(TestNewtype2, ::sha256d::Hash, 32, doc="A test newtype");
#[test]
fn convert_newtypes() {
let h1 = TestNewtype::hash(&[]);
let h2: TestNewtype2 = h1.as_hash().into();
assert_eq!(&h1[..], &h2[..]);
}
}