From 4a7cf34eeb880af5841159b17ddaf007c459e145 Mon Sep 17 00:00:00 2001 From: Nadav Ivgi Date: Wed, 6 Jan 2021 00:01:21 +0200 Subject: [PATCH] Use efficient serialization for non-human-readable formats --- Cargo.toml | 1 + src/lib.rs | 1 + src/util/uint.rs | 28 +++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 59b22722..9f3a5843 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,5 +34,6 @@ serde = { version = "1", features = [ "derive" ], optional = true } serde_json = "<1.0.45" serde_test = "1" secp256k1 = { version = "0.20.0", features = [ "recovery", "rand-std" ] } +bincode = "1.3.1" # We need to pin ryu (transitive dep from serde_json) to stay compatible with Rust 1.22.0 ryu = "<1.0.5" diff --git a/src/lib.rs b/src/lib.rs index 7007cf9e..e7387de4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub extern crate bech32; #[cfg(feature = "serde")] #[macro_use] extern crate serde; #[cfg(all(test, feature = "serde"))] extern crate serde_json; #[cfg(all(test, feature = "serde"))] extern crate serde_test; +#[cfg(all(test, feature = "serde"))] extern crate bincode; #[cfg(all(test, feature = "unstable"))] extern crate test; #[cfg(target_pointer_width = "16")] diff --git a/src/util/uint.rs b/src/util/uint.rs index a4c0fedb..47968a69 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -436,7 +436,12 @@ macro_rules! construct_uint { S: $crate::serde::Serializer, { use $crate::hashes::hex::ToHex; - serializer.serialize_str(&self.to_be_bytes().to_hex()) + let bytes = self.to_be_bytes(); + if serializer.is_human_readable() { + serializer.serialize_str(&bytes.to_hex()) + } else { + serializer.serialize_bytes(&bytes) + } } } @@ -453,7 +458,7 @@ macro_rules! construct_uint { type Value = $name; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "hex string with {} characters ({} bytes", $n_words * 8 * 2, $n_words * 8) + write!(f, "{} bytes or a hex string with {} characters", $n_words * 8, $n_words * 8 * 2) } fn visit_str(self, s: &str) -> Result @@ -465,8 +470,21 @@ macro_rules! construct_uint { $name::from_be_slice(&bytes) .map_err(|_| de::Error::invalid_length(bytes.len() * 2, &self)) } + + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: de::Error, + { + $name::from_be_slice(bytes) + .map_err(|_| de::Error::invalid_length(bytes.len(), &self)) + } + } + + if deserializer.is_human_readable() { + deserializer.deserialize_str(Visitor) + } else { + deserializer.deserialize_bytes(Visitor) } - deserializer.deserialize_str(Visitor) } } ); @@ -703,6 +721,10 @@ mod tests { let json = format!("\"{}\"", hex); assert_eq!(::serde_json::to_string(&uint).unwrap(), json); assert_eq!(::serde_json::from_str::(&json).unwrap(), uint); + + let bin_encoded = ::bincode::serialize(&uint).unwrap(); + let bin_decoded: Uint256 = ::bincode::deserialize(&bin_encoded).unwrap(); + assert_eq!(bin_decoded, uint); }; check(