Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

Add hash_newtype macro #59

Merged
merged 4 commits into from Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,8 @@

# 0.7.1 - 2019-08-14

* Add hash_newtype macro that allows third parties to create newtype structs.

# 0.7.0 - 2019-07-19

* Add `hex::Error` type for errors generated by the `hex` module.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "bitcoin_hashes"
version = "0.7.0"
version = "0.7.1"
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
license = "CC0-1.0"
description = "Hash functions used by rust-bitcoin which support rustc 1.14.0"
Expand Down
63 changes: 63 additions & 0 deletions src/lib.rs
Expand Up @@ -124,3 +124,66 @@ pub trait Hash: Copy + Clone + PartialEq + Eq + Default + PartialOrd + Ord +
/// Constructs a hash from the underlying byte array
fn from_inner(inner: Self::Inner) -> Self;
}

/// Create a new newtype around a [Hash] type.
#[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 ::hex::FromHex for $newtype {
fn from_byte_iter<I>(iter: I) -> Result<Self, ::hex::Error>
where I: Iterator<Item=Result<u8, ::hex::Error>> +
ExactSizeIterator +
DoubleEndedIterator,
{
Ok($newtype(::hex::FromHex::from_byte_iter(iter)?))
}
}

impl ::std::str::FromStr for $newtype {
type Err = ::hex::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
::hex::FromHex::from_hex(s)
}
}

impl $newtype {
/// The length in bytes.
pub const LEN: usize = <$hash as ::Hash>::LEN;

/// Whether this type should be displayed backwards.
pub const DISPLAY_BACKWARD: bool = <$hash as ::Hash>::DISPLAY_BACKWARD;

/// Construct from the inner value.
pub fn from_inner(inner: $hash) -> Self {
$newtype(inner)
}

/// Construct from a byte slice.
pub fn from_slice(sl: &[u8]) -> Result<$newtype, ::error::Error> {
Ok($newtype(<$hash as ::Hash>::from_slice(sl)?))
}

/// Unwraps and returns the underlying value.
pub fn into_inner(self) -> $hash {
self.0
}
}
};
}

#[cfg(test)]
mod test {
hash_newtype!(TestNewtype, ::sha256d::Hash, 32, doc="A test newtype");
}

11 changes: 4 additions & 7 deletions src/serde_macros.rs
Expand Up @@ -63,13 +63,10 @@ macro_rules! serde_impl(
where
E: ::serde::de::Error,
{
if v.len() != $t::LEN {
Err(E::invalid_length(v.len(), &stringify!($len)))
} else {
let mut ret = [0; $len];
ret.copy_from_slice(v);
Ok($t(ret))
}
$t::from_slice(v).map_err(|_| {
// from_slice only errors on incorrect length
E::invalid_length(v.len(), &stringify!($len))
})
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/sha256.rs
Expand Up @@ -145,6 +145,13 @@ index_impl!(Midstate);
serde_impl!(Midstate, 32);
borrow_slice_impl!(Midstate);

impl str::FromStr for Midstate {
type Err = ::hex::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
::hex::FromHex::from_hex(s)
}
}

impl Midstate {
/// Length of the midstate, in bytes.
const LEN: usize = 32;
Expand Down