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

Commit

Permalink
Merge pull request #36 from rust-bitcoin/2019-03-serdefix
Browse files Browse the repository at this point in the history
fix non-human-readable serde deserialization
  • Loading branch information
apoelstra authored Mar 4, 2019
2 parents 1bac99e + b14fe9e commit a2ff38e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bitcoin_hashes"
version = "0.3.0"
version = "0.3.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
62 changes: 52 additions & 10 deletions src/serde_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,63 @@ macro_rules! serde_impl(

impl<'de> ::serde::Deserialize<'de> for $t {
fn deserialize<D: ::serde::Deserializer<'de>>(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<E>(self, v: &[u8]) -> Result<Self::Value, E>
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<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
$t::from_hex(v).map_err(E::custom)
}
}

d.deserialize_str(HexVisitor)
} 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<E>(self, v: &[u8]) -> Result<Self::Value, E>
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)
}
}
}
Expand Down

0 comments on commit a2ff38e

Please sign in to comment.