From 113d11270eb352e4398218980f2776114c9a9a13 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Fri, 26 Aug 2022 12:19:14 +0100 Subject: [PATCH 1/6] Support deserializing from borrowed or owned bytes, too --- primitive-types/impls/serde/src/serialize.rs | 94 +++++++++++++++++++- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/primitive-types/impls/serde/src/serialize.rs b/primitive-types/impls/serde/src/serialize.rs index ee3a57c05..0a6fb294b 100644 --- a/primitive-types/impls/serde/src/serialize.rs +++ b/primitive-types/impls/serde/src/serialize.rs @@ -187,8 +187,8 @@ pub enum ExpectedLen<'a> { impl<'a> fmt::Display for ExpectedLen<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { - ExpectedLen::Exact(ref v) => write!(fmt, "length of {}", v.len() * 2), - ExpectedLen::Between(min, ref v) => write!(fmt, "length between ({}; {}]", min * 2, v.len() * 2), + ExpectedLen::Exact(ref v) => write!(fmt, "{} bytes", v.len()), + ExpectedLen::Between(min, ref v) => write!(fmt, "between ({}; {}] bytes", min, v.len()), } } } @@ -205,7 +205,7 @@ where type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a (both 0x-prefixed or not) hex string") + write!(formatter, "a (both 0x-prefixed or not) hex string or byte array") } fn visit_str(self, v: &str) -> Result { @@ -215,6 +215,14 @@ where fn visit_string(self, v: String) -> Result { self.visit_str(&v) } + + fn visit_bytes(self, v: &[u8]) -> Result { + Ok(v.to_vec()) + } + + fn visit_byte_buf(self, v: Vec) -> Result { + Ok(v) + } } deserializer.deserialize_str(Visitor) @@ -234,7 +242,7 @@ where type Value = usize; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a (both 0x-prefixed or not) hex string with {}", self.len) + write!(formatter, "a (both 0x-prefixed or not) hex string or byte array containing {}", self.len) } fn visit_str(self, v: &str) -> Result { @@ -261,6 +269,32 @@ where fn visit_string(self, v: String) -> Result { self.visit_str(&v) } + + fn visit_bytes(self, v: &[u8]) -> Result { + let len = v.len(); + let is_len_valid = match self.len { + ExpectedLen::Exact(ref slice) => len == slice.len(), + ExpectedLen::Between(min, ref slice) => len <= slice.len() && len > min, + }; + + if !is_len_valid { + return Err(E::invalid_length(v.len(), &self)) + } + + let bytes = match self.len { + ExpectedLen::Exact(slice) => slice, + ExpectedLen::Between(_, slice) => slice, + }; + + for (index, byte) in v.iter().enumerate() { + bytes[index] = *byte; + } + Ok(len) + } + + fn visit_byte_buf(self, v: Vec) -> Result { + self.visit_bytes(&v) + } } deserializer.deserialize_str(Visitor { len }) @@ -367,4 +401,56 @@ mod tests { assert_eq!(from_hex("102"), Ok(vec![1, 2])); assert_eq!(from_hex("f"), Ok(vec![0xf])); } + + #[test] + fn should_deserialize_from_owned_bytes() { + type BytesDeserializer<'a> = serde::de::value::BytesDeserializer<'a, serde::de::value::Error>; + + // using `deserialize` to decode owned bytes. + let des = BytesDeserializer::new(&[1,2,3,4,5]); + let deserialized: Vec = deserialize(des).unwrap(); + assert_eq!(deserialized, vec![1,2,3,4,5]); + + // using `deserialize` to decode owned bytes into buffer with fixed length. + let des = BytesDeserializer::new(&[1,2,3,4,5]); + let mut output = vec![0,0,0,0,0]; + let expected_len = ExpectedLen::Exact(&mut *output); + let n = deserialize_check_len(des, expected_len).unwrap(); + assert_eq!(n, 5); + assert_eq!(output, vec![1,2,3,4,5]); + + // using `deserialize` to decode owned bytes into buffer with min/max length. + let des = BytesDeserializer::new(&[1,2,3]); + let mut output = vec![0,0,0,0,0]; + let expected_len = ExpectedLen::Between(2, &mut *output); + let n = deserialize_check_len(des, expected_len).unwrap(); + assert_eq!(n, 3); + assert_eq!(output, vec![1,2,3,0,0]); + } + + #[test] + fn should_deserialize_from_borrowed_bytes() { + type BytesDeserializer<'a> = serde::de::value::BorrowedBytesDeserializer<'a, serde::de::value::Error>; + + // using `deserialize` to decode owned bytes. + let des = BytesDeserializer::new(&[1,2,3,4,5]); + let deserialized: Vec = deserialize(des).unwrap(); + assert_eq!(deserialized, vec![1,2,3,4,5]); + + // using `deserialize` to decode owned bytes into buffer with fixed length. + let des = BytesDeserializer::new(&[1,2,3,4,5]); + let mut output = vec![0,0,0,0,0]; + let expected_len = ExpectedLen::Exact(&mut *output); + let n = deserialize_check_len(des, expected_len).unwrap(); + assert_eq!(n, 5); + assert_eq!(output, vec![1,2,3,4,5]); + + // using `deserialize` to decode owned bytes into buffer with min/max length. + let des = BytesDeserializer::new(&[1,2,3]); + let mut output = vec![0,0,0,0,0]; + let expected_len = ExpectedLen::Between(2, &mut *output); + let n = deserialize_check_len(des, expected_len).unwrap(); + assert_eq!(n, 3); + assert_eq!(output, vec![1,2,3,0,0]); + } } From 9d836d714d54fc1b1cc7c3bd292d1540447ca24b Mon Sep 17 00:00:00 2001 From: James Wilson Date: Fri, 26 Aug 2022 12:28:23 +0100 Subject: [PATCH 2/6] cargo fmt --- primitive-types/impls/serde/src/serialize.rs | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/primitive-types/impls/serde/src/serialize.rs b/primitive-types/impls/serde/src/serialize.rs index 0a6fb294b..39e4dc5d8 100644 --- a/primitive-types/impls/serde/src/serialize.rs +++ b/primitive-types/impls/serde/src/serialize.rs @@ -407,25 +407,25 @@ mod tests { type BytesDeserializer<'a> = serde::de::value::BytesDeserializer<'a, serde::de::value::Error>; // using `deserialize` to decode owned bytes. - let des = BytesDeserializer::new(&[1,2,3,4,5]); + let des = BytesDeserializer::new(&[1, 2, 3, 4, 5]); let deserialized: Vec = deserialize(des).unwrap(); - assert_eq!(deserialized, vec![1,2,3,4,5]); + assert_eq!(deserialized, vec![1, 2, 3, 4, 5]); // using `deserialize` to decode owned bytes into buffer with fixed length. - let des = BytesDeserializer::new(&[1,2,3,4,5]); - let mut output = vec![0,0,0,0,0]; + let des = BytesDeserializer::new(&[1, 2, 3, 4, 5]); + let mut output = vec![0, 0, 0, 0, 0]; let expected_len = ExpectedLen::Exact(&mut *output); let n = deserialize_check_len(des, expected_len).unwrap(); assert_eq!(n, 5); - assert_eq!(output, vec![1,2,3,4,5]); + assert_eq!(output, vec![1, 2, 3, 4, 5]); // using `deserialize` to decode owned bytes into buffer with min/max length. - let des = BytesDeserializer::new(&[1,2,3]); - let mut output = vec![0,0,0,0,0]; + let des = BytesDeserializer::new(&[1, 2, 3]); + let mut output = vec![0, 0, 0, 0, 0]; let expected_len = ExpectedLen::Between(2, &mut *output); let n = deserialize_check_len(des, expected_len).unwrap(); assert_eq!(n, 3); - assert_eq!(output, vec![1,2,3,0,0]); + assert_eq!(output, vec![1, 2, 3, 0, 0]); } #[test] @@ -433,24 +433,24 @@ mod tests { type BytesDeserializer<'a> = serde::de::value::BorrowedBytesDeserializer<'a, serde::de::value::Error>; // using `deserialize` to decode owned bytes. - let des = BytesDeserializer::new(&[1,2,3,4,5]); + let des = BytesDeserializer::new(&[1, 2, 3, 4, 5]); let deserialized: Vec = deserialize(des).unwrap(); - assert_eq!(deserialized, vec![1,2,3,4,5]); + assert_eq!(deserialized, vec![1, 2, 3, 4, 5]); // using `deserialize` to decode owned bytes into buffer with fixed length. - let des = BytesDeserializer::new(&[1,2,3,4,5]); - let mut output = vec![0,0,0,0,0]; + let des = BytesDeserializer::new(&[1, 2, 3, 4, 5]); + let mut output = vec![0, 0, 0, 0, 0]; let expected_len = ExpectedLen::Exact(&mut *output); let n = deserialize_check_len(des, expected_len).unwrap(); assert_eq!(n, 5); - assert_eq!(output, vec![1,2,3,4,5]); + assert_eq!(output, vec![1, 2, 3, 4, 5]); // using `deserialize` to decode owned bytes into buffer with min/max length. - let des = BytesDeserializer::new(&[1,2,3]); - let mut output = vec![0,0,0,0,0]; + let des = BytesDeserializer::new(&[1, 2, 3]); + let mut output = vec![0, 0, 0, 0, 0]; let expected_len = ExpectedLen::Between(2, &mut *output); let n = deserialize_check_len(des, expected_len).unwrap(); assert_eq!(n, 3); - assert_eq!(output, vec![1,2,3,0,0]); + assert_eq!(output, vec![1, 2, 3, 0, 0]); } } From 858da4d03b4eb2f560883f5c3d17fb34b7f615d8 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Fri, 26 Aug 2022 13:35:38 +0100 Subject: [PATCH 3/6] Fix comments --- primitive-types/impls/serde/src/serialize.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/primitive-types/impls/serde/src/serialize.rs b/primitive-types/impls/serde/src/serialize.rs index 39e4dc5d8..fd87cb2ca 100644 --- a/primitive-types/impls/serde/src/serialize.rs +++ b/primitive-types/impls/serde/src/serialize.rs @@ -432,12 +432,12 @@ mod tests { fn should_deserialize_from_borrowed_bytes() { type BytesDeserializer<'a> = serde::de::value::BorrowedBytesDeserializer<'a, serde::de::value::Error>; - // using `deserialize` to decode owned bytes. + // using `deserialize` to decode borrowed bytes. let des = BytesDeserializer::new(&[1, 2, 3, 4, 5]); let deserialized: Vec = deserialize(des).unwrap(); assert_eq!(deserialized, vec![1, 2, 3, 4, 5]); - // using `deserialize` to decode owned bytes into buffer with fixed length. + // using `deserialize` to decode borrowed bytes into buffer with fixed length. let des = BytesDeserializer::new(&[1, 2, 3, 4, 5]); let mut output = vec![0, 0, 0, 0, 0]; let expected_len = ExpectedLen::Exact(&mut *output); @@ -445,7 +445,7 @@ mod tests { assert_eq!(n, 5); assert_eq!(output, vec![1, 2, 3, 4, 5]); - // using `deserialize` to decode owned bytes into buffer with min/max length. + // using `deserialize` to decode borrowed bytes into buffer with min/max length. let des = BytesDeserializer::new(&[1, 2, 3]); let mut output = vec![0, 0, 0, 0, 0]; let expected_len = ExpectedLen::Between(2, &mut *output); From b61097c326ad3dc6c91f1d9888cc4bbb094c13b9 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 31 Aug 2022 16:48:52 +0100 Subject: [PATCH 4/6] H256 et al can deserialize u8 sequences, too --- primitive-types/impls/serde/src/serialize.rs | 46 ++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/primitive-types/impls/serde/src/serialize.rs b/primitive-types/impls/serde/src/serialize.rs index fd87cb2ca..1426d3ddf 100644 --- a/primitive-types/impls/serde/src/serialize.rs +++ b/primitive-types/impls/serde/src/serialize.rs @@ -223,6 +223,14 @@ where fn visit_byte_buf(self, v: Vec) -> Result { Ok(v) } + + fn visit_seq>(self, mut seq: A) -> Result { + let mut bytes = vec![]; + while let Some(n) = seq.next_element::()? { + bytes.push(n); + } + Ok(bytes) + } } deserializer.deserialize_str(Visitor) @@ -286,15 +294,21 @@ where ExpectedLen::Between(_, slice) => slice, }; - for (index, byte) in v.iter().enumerate() { - bytes[index] = *byte; - } + bytes[..len].copy_from_slice(v); Ok(len) } fn visit_byte_buf(self, v: Vec) -> Result { self.visit_bytes(&v) } + + fn visit_seq>(self, mut seq: A) -> Result { + let mut v = vec![]; + while let Some(n) = seq.next_element::()? { + v.push(n); + } + self.visit_byte_buf(v) + } } deserializer.deserialize_str(Visitor { len }) @@ -453,4 +467,30 @@ mod tests { assert_eq!(n, 3); assert_eq!(output, vec![1, 2, 3, 0, 0]); } + + #[test] + fn should_deserialize_from_u8_sequence() { + use serde::de::value::SeqDeserializer; + + // using `deserialize` to decode a sequence of bytes. + let des = SeqDeserializer::<_, serde::de::value::Error>::new([1u8, 2, 3, 4, 5].into_iter()); + let deserialized: Vec = deserialize(des).unwrap(); + assert_eq!(deserialized, vec![1, 2, 3, 4, 5]); + + // using `deserialize` to decode a sequence of bytes into a buffer with fixed length. + let des = SeqDeserializer::<_, serde::de::value::Error>::new([1u8, 2, 3, 4, 5].into_iter()); + let mut output = vec![0, 0, 0, 0, 0]; + let expected_len = ExpectedLen::Exact(&mut *output); + let n = deserialize_check_len(des, expected_len).unwrap(); + assert_eq!(n, 5); + assert_eq!(output, vec![1, 2, 3, 4, 5]); + + // using `deserialize` to decode a sequence of bytes into a buffer with min/max length. + let des = SeqDeserializer::<_, serde::de::value::Error>::new([1u8, 2, 3].into_iter()); + let mut output = vec![0, 0, 0, 0, 0]; + let expected_len = ExpectedLen::Between(2, &mut *output); + let n = deserialize_check_len(des, expected_len).unwrap(); + assert_eq!(n, 3); + assert_eq!(output, vec![1, 2, 3, 0, 0]); + } } From 7ac2dcda54341ff268ff9b1b537079006e1eb9f2 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 31 Aug 2022 17:26:37 +0100 Subject: [PATCH 5/6] add changelog entry and bump version ready for release --- primitive-types/impls/serde/CHANGELOG.md | 3 ++- primitive-types/impls/serde/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/primitive-types/impls/serde/CHANGELOG.md b/primitive-types/impls/serde/CHANGELOG.md index 5d143f916..43c06ddf5 100644 --- a/primitive-types/impls/serde/CHANGELOG.md +++ b/primitive-types/impls/serde/CHANGELOG.md @@ -4,7 +4,8 @@ The format is based on [Keep a Changelog]. [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ -## [Unreleased] +## [0.4.0] - 2022-08-31 +- Support deserializing H256 et al from bytes or sequences of bytes, too. [#668](https://github.com/paritytech/parity-common/pull/668) - Migrated to 2021 edition, enforcing MSRV of `1.56.1`. [#601](https://github.com/paritytech/parity-common/pull/601) ## [0.3.2] - 2021-11-10 diff --git a/primitive-types/impls/serde/Cargo.toml b/primitive-types/impls/serde/Cargo.toml index f94c754ac..91915edf9 100644 --- a/primitive-types/impls/serde/Cargo.toml +++ b/primitive-types/impls/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "impl-serde" -version = "0.3.2" +version = "0.4.0" authors = ["Parity Technologies "] license = "MIT OR Apache-2.0" homepage = "https://github.com/paritytech/parity-common" From 543261fb4d28a0f3166a6372a93f0a31adc185f1 Mon Sep 17 00:00:00 2001 From: Andronik Date: Wed, 31 Aug 2022 18:36:13 +0200 Subject: [PATCH 6/6] propagate the bump --- ethbloom/Cargo.toml | 2 +- ethereum-types/Cargo.toml | 2 +- primitive-types/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethbloom/Cargo.toml b/ethbloom/Cargo.toml index 95a84eebb..df2b546a0 100644 --- a/ethbloom/Cargo.toml +++ b/ethbloom/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.56.1" tiny-keccak = { version = "2.0", features = ["keccak"] } crunchy = { version = "0.2.2", default-features = false, features = ["limit_256"] } fixed-hash = { path = "../fixed-hash", version = "0.7", default-features = false } -impl-serde = { path = "../primitive-types/impls/serde", version = "0.3", default-features = false, optional = true } +impl-serde = { path = "../primitive-types/impls/serde", version = "0.4", default-features = false, optional = true } impl-rlp = { path = "../primitive-types/impls/rlp", version = "0.3", default-features = false, optional = true } impl-codec = { version = "0.6.0", path = "../primitive-types/impls/codec", default-features = false, optional = true } scale-info = { version = ">=1.0, <3", features = ["derive"], default-features = false, optional = true } diff --git a/ethereum-types/Cargo.toml b/ethereum-types/Cargo.toml index 3449beccd..596e8364f 100644 --- a/ethereum-types/Cargo.toml +++ b/ethereum-types/Cargo.toml @@ -13,7 +13,7 @@ ethbloom = { path = "../ethbloom", version = "0.12", default-features = false } fixed-hash = { path = "../fixed-hash", version = "0.7", default-features = false, features = ["byteorder", "rustc-hex"] } uint-crate = { path = "../uint", package = "uint", version = "0.9", default-features = false } primitive-types = { path = "../primitive-types", version = "0.11", features = ["byteorder", "rustc-hex"], default-features = false } -impl-serde = { path = "../primitive-types/impls/serde", version = "0.3.2", default-features = false, optional = true } +impl-serde = { path = "../primitive-types/impls/serde", version = "0.4.0", default-features = false, optional = true } impl-rlp = { path = "../primitive-types/impls/rlp", version = "0.3", default-features = false, optional = true } impl-codec = { version = "0.6.0", path = "../primitive-types/impls/codec", default-features = false, optional = true } scale-info = { version = ">=1.0, <3", features = ["derive"], default-features = false, optional = true } diff --git a/primitive-types/Cargo.toml b/primitive-types/Cargo.toml index f65c10507..5eb5ec049 100644 --- a/primitive-types/Cargo.toml +++ b/primitive-types/Cargo.toml @@ -11,7 +11,7 @@ rust-version = "1.60.0" [dependencies] fixed-hash = { version = "0.7", path = "../fixed-hash", default-features = false } uint = { version = "0.9.0", path = "../uint", default-features = false } -impl-serde = { version = "0.3.1", path = "impls/serde", default-features = false, optional = true } +impl-serde = { version = "0.4.0", path = "impls/serde", default-features = false, optional = true } impl-codec = { version = "0.6.0", path = "impls/codec", default-features = false, optional = true } impl-num-traits = { version = "0.1.0", path = "impls/num-traits", default-features = false, optional = true } impl-rlp = { version = "0.3", path = "impls/rlp", default-features = false, optional = true }