From ad8791f174ca704bf36909743fe06fff3ac2723d Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 2 Mar 2019 00:56:29 +0000 Subject: [PATCH 1/3] serde: use `visit_bytes` instead of `visit_borrowed_bytes` to deserialize hashes --- src/serde_macros.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/serde_macros.rs b/src/serde_macros.rs index 5d7d9a8..cb4491a 100644 --- a/src/serde_macros.rs +++ b/src/serde_macros.rs @@ -24,14 +24,30 @@ macro_rules! serde_impl( let sl: String = ::serde::Deserialize::deserialize(d)?; $t::from_hex(&sl).map_err(D::Error::custom) } else { - let sl: &[u8] = ::serde::Deserialize::deserialize(d)?; - if sl.len() != $t::LEN { - Err(D::Error::invalid_length(sl.len(), &stringify!($len))) - } else { - let mut ret = [0; $len]; - ret.copy_from_slice(sl); - Ok($t(ret)) + struct BytesVisitor; + + impl<'de> ::serde::de::Visitor<'de> for BytesVisitor { + type Value = $t; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> Result + 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)) + } + } } + + d.deserialize_bytes(BytesVisitor) } } } From bc61e91c470e6b35a7ab36de24e3fc0e8dfc3147 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 2 Mar 2019 01:57:13 +0000 Subject: [PATCH 2/3] serde: remove allocation from the human-readable deserializer --- src/serde_macros.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/serde_macros.rs b/src/serde_macros.rs index cb4491a..922fa24 100644 --- a/src/serde_macros.rs +++ b/src/serde_macros.rs @@ -17,12 +17,38 @@ macro_rules! serde_impl( impl<'de> ::serde::Deserialize<'de> for $t { fn deserialize>(d: D) -> Result<$t, D::Error> { - use ::serde::de::Error; use hex::FromHex; if d.is_human_readable() { - let sl: String = ::serde::Deserialize::deserialize(d)?; - $t::from_hex(&sl).map_err(D::Error::custom) + struct HexVisitor; + + impl<'de> ::serde::de::Visitor<'de> for HexVisitor { + type Value = $t; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + if let Ok(hex) = ::std::str::from_utf8(v) { + $t::from_hex(hex).map_err(E::custom) + } else { + return Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)); + } + } + + fn visit_str(self, v: &str) -> Result + where + E: ::serde::de::Error, + { + $t::from_hex(v).map_err(E::custom) + } + } + + d.deserialize_str(HexVisitor) } else { struct BytesVisitor; From b14fe9ed5cef424f32c04cb92fcb0c1d6149b4bb Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Sat, 2 Mar 2019 00:56:57 +0000 Subject: [PATCH 3/3] bump minor version to 0.3.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4759e3b..979cb1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitcoin_hashes" -version = "0.3.0" +version = "0.3.1" authors = ["Andrew Poelstra "] license = "CC0-1.0" description = "Hash functions used by rust-bitcoin which support rustc 1.14.0"