#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(bench, feature(test))]
#![warn(missing_docs)]
#![cfg_attr(hashes_fuzz, allow(dead_code, unused_imports))]
#![allow(clippy::needless_question_mark)] #![allow(clippy::manual_range_contains)] #![allow(clippy::needless_borrows_for_generic_args)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(any(test, feature = "std"))]
extern crate core;
#[cfg(feature = "serde")]
pub extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_test;
#[cfg(bench)]
extern crate test;
pub extern crate hex;
#[doc(hidden)]
pub mod _export {
pub mod _core {
pub use core::*;
}
}
#[cfg(feature = "schemars")]
extern crate actual_schemars as schemars;
mod internal_macros;
#[macro_use]
mod util;
#[macro_use]
pub mod serde_macros;
pub mod cmp;
pub mod hash160;
pub mod hmac;
#[cfg(feature = "bitcoin-io")]
mod impls;
pub mod ripemd160;
pub mod sha1;
pub mod sha256;
pub mod sha256d;
pub mod sha256t;
pub mod sha384;
pub mod sha512;
pub mod sha512_256;
pub mod siphash24;
use core::{borrow, fmt, hash, ops};
pub use hmac::{Hmac, HmacEngine};
pub trait HashEngine: Clone + Default {
type MidState;
fn midstate(&self) -> Self::MidState;
const BLOCK_SIZE: usize;
fn input(&mut self, data: &[u8]);
fn n_bytes_hashed(&self) -> usize;
}
pub trait Hash:
Copy
+ Clone
+ PartialEq
+ Eq
+ 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 Bytes: hex::FromHex + Copy;
fn engine() -> Self::Engine { Self::Engine::default() }
fn from_engine(e: Self::Engine) -> Self;
const LEN: usize;
fn from_slice(sl: &[u8]) -> Result<Self, FromSliceError>;
fn hash(data: &[u8]) -> Self {
let mut engine = Self::engine();
engine.input(data);
Self::from_engine(engine)
}
fn hash_byte_chunks<B, I>(byte_slices: I) -> Self
where
B: AsRef<[u8]>,
I: IntoIterator<Item = B>,
{
let mut engine = Self::engine();
for slice in byte_slices {
engine.input(slice.as_ref());
}
Self::from_engine(engine)
}
const DISPLAY_BACKWARD: bool = false;
fn to_byte_array(self) -> Self::Bytes;
fn as_byte_array(&self) -> &Self::Bytes;
fn from_byte_array(bytes: Self::Bytes) -> Self;
fn all_zeros() -> Self;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FromSliceError {
expected: usize,
got: usize,
}
impl FromSliceError {
pub fn expected_length(&self) -> usize { self.expected }
pub fn invalid_length(&self) -> usize { self.got }
}
impl fmt::Display for FromSliceError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "invalid slice length {} (expected {})", self.got, self.expected)
}
}
#[cfg(feature = "std")]
impl std::error::Error for FromSliceError {}
#[cfg(test)]
mod tests {
use crate::{sha256d, Hash};
hash_newtype! {
struct TestNewtype(sha256d::Hash);
struct TestNewtype2(sha256d::Hash);
}
#[test]
fn convert_newtypes() {
let h1 = TestNewtype::hash(&[]);
let h2: TestNewtype2 = h1.to_raw_hash().into();
assert_eq!(&h1[..], &h2[..]);
let h = sha256d::Hash::hash(&[]);
let h2: TestNewtype = h.to_string().parse().unwrap();
assert_eq!(h2.to_raw_hash(), h);
}
#[test]
fn newtype_fmt_roundtrip() {
let orig = TestNewtype::hash(&[]);
let hex = format!("{}", orig);
let rinsed = hex.parse::<TestNewtype>().expect("failed to parse hex");
assert_eq!(rinsed, orig)
}
}