diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 42ecab58..5b0bb2f8 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -823,44 +823,59 @@ impl_index_newtype!(Builder, u8); #[cfg(feature = "serde")] impl<'de> serde::Deserialize<'de> for Script { fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, + where D: serde::Deserializer<'de>, { use core::fmt::Formatter; use hashes::hex::FromHex; - struct Visitor; - impl<'de> serde::de::Visitor<'de> for Visitor { - type Value = Script; + if deserializer.is_human_readable() { - fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { - formatter.write_str("a script") - } + struct Visitor; + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = Script; - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - let v = Vec::from_hex(v).map_err(E::custom)?; - Ok(Script::from(v)) - } + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + formatter.write_str("a script hex") + } - fn visit_borrowed_str(self, v: &'de str) -> Result - where - E: serde::de::Error, - { - self.visit_str(v) - } + fn visit_str(self, v: &str) -> Result + where E: serde::de::Error, + { + let v = Vec::from_hex(v).map_err(E::custom)?; + Ok(Script::from(v)) + } - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, - { - self.visit_str(&v) + fn visit_borrowed_str(self, v: &'de str) -> Result + where E: serde::de::Error, + { + self.visit_str(v) + } + + fn visit_string(self, v: String) -> Result + where E: serde::de::Error, + { + self.visit_str(&v) + } } + deserializer.deserialize_str(Visitor) + } else { + struct BytesVisitor; + + impl<'de> serde::de::Visitor<'de> for BytesVisitor { + type Value = Script; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + formatter.write_str("a script Vec") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: serde::de::Error, + { + Ok(Script::from(v.to_vec())) + } + } + deserializer.deserialize_bytes(BytesVisitor) } - - deserializer.deserialize_str(Visitor) } } @@ -871,7 +886,11 @@ impl serde::Serialize for Script { where S: serde::Serializer, { - serializer.serialize_str(&format!("{:x}", self)) + if serializer.is_human_readable() { + serializer.serialize_str(&format!("{:x}", self)) + } else { + serializer.serialize_bytes(&self.as_bytes()) + } } } @@ -1278,5 +1297,22 @@ mod test { assert!(script_p2pkh.is_p2pkh()); assert_eq!(script_p2pkh.dust_value(), ::Amount::from_sat(546)); } + + #[test] + #[cfg(feature = "serde")] + fn test_script_serde_human_and_not() { + let script = Script::from(vec![0u8, 1u8, 2u8]); + + // Serialize + let json = ::serde_json::to_string(&script).unwrap(); + assert_eq!(json, "\"000102\""); + let bincode = ::bincode::serialize(&script).unwrap(); + assert_eq!(bincode, [3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2]); // bincode adds u64 for length, serde_cbor use varint + + // Deserialize + assert_eq!(script, ::serde_json::from_str(&json).unwrap()); + assert_eq!(script, ::bincode::deserialize(&bincode).unwrap()); + } + }