Skip to content

Commit 0841cc4

Browse files
BREAKING CHANGE: DecodeLimit and DecodeAll extensions now advance input (paritytech#314)
* BREAKING CHANGE: DecodeLimit and DecodeAll extensions now properly advance input * Prepare for release 3.0.0 * This repo uses hard tabs
1 parent 2bffcf9 commit 0841cc4

7 files changed

Lines changed: 94 additions & 67 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,21 @@ All notable changes to this crate are documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this crate adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## Unreleased
8+
## [3.0.0] - 2022-02-02
9+
10+
### Fix
11+
12+
- Optimised the Decode::decode for [T; N] [#299](https://github.com/paritytech/parity-scale-codec/pull/299)
13+
14+
### Changed
15+
916
- Migrated to 2021 edition, enforcing MSRV of `1.56.1`. [#298](https://github.com/paritytech/parity-scale-codec/pull/298)
17+
- Upgrade to BitVec 1.0 [#311](https://github.com/paritytech/parity-scale-codec/pull/311)
18+
- DecodeLimit and DecodeAll extensions now advance input [#314](https://github.com/paritytech/parity-scale-codec/pull/314)
19+
20+
### Added
21+
22+
- Add bytes::Bytes implementation [#309](https://github.com/paritytech/parity-scale-codec/pull/309)
1023

1124
## [2.3.1] - 2021-09-28
1225

@@ -17,6 +30,7 @@ and this crate adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
1730
## [2.3.0] - 2021-09-11
1831

1932
### Added
33+
2034
- `decode_and_advance_with_depth_limit` to the `DecodeLimit` trait. This allows advancing the cursor while decoding the input. PR #286
2135

2236
## [2.2.0] - 2021-07-02

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "parity-scale-codec"
33
description = "SCALE - Simple Concatenating Aggregated Little Endians"
4-
version = "2.3.1"
4+
version = "3.0.0"
55
authors = ["Parity Technologies <admin@parity.io>"]
66
license = "Apache-2.0"
77
repository = "https://github.com/paritytech/parity-scale-codec"
@@ -12,8 +12,8 @@ rust-version = "1.56.1"
1212
[dependencies]
1313
arrayvec = { version = "0.7", default-features = false }
1414
serde = { version = "1.0.102", optional = true }
15-
parity-scale-codec-derive = { path = "derive", version = "2.3.1", default-features = false, optional = true }
16-
bitvec = { version = "1", default-features = false, features = ["alloc"], optional = true }
15+
parity-scale-codec-derive = { path = "derive", version = "3.0.0", default-features = false, optional = true }
16+
bitvec = { version = "1", default-features = false, features = [ "alloc" ], optional = true }
1717
bytes = { version = "1", default-features = false, optional = true }
1818
byte-slice-cast = { version = "1.0.0", default-features = false }
1919
generic-array = { version = "0.14.4", optional = true }
@@ -59,7 +59,4 @@ chain-error = []
5959
full = []
6060

6161
[workspace]
62-
members = [
63-
"derive",
64-
"fuzzer",
65-
]
62+
members = ["derive", "fuzzer"]

derive/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "parity-scale-codec-derive"
33
description = "Serialization and deserialization derive macro for Parity SCALE Codec"
4-
version = "2.3.1"
4+
version = "3.0.0"
55
authors = ["Parity Technologies <admin@parity.io>"]
66
license = "Apache-2.0"
77
edition = "2021"

rustfmt.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Basic
2+
hard_tabs = true
3+
max_width = 100
4+
use_small_heuristics = "Max"
5+
# Imports
6+
imports_granularity = "Crate"
7+
reorder_imports = true
8+
# Consistency
9+
newline_style = "Unix"
10+
# Format comments
11+
comment_width = 100
12+
wrap_comments = true
13+
# Misc
14+
chain_width = 80
15+
spaces_around_ranges = false
16+
binop_separator = "Back"
17+
reorder_impl_items = false
18+
match_arm_leading_pipes = "Preserve"
19+
match_arm_blocks = false
20+
match_block_trailing_comma = true
21+
trailing_comma = "Vertical"
22+
trailing_semicolon = false
23+
use_field_init_shorthand = true

src/decode_all.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use crate::{Error, Decode};
15+
use crate::{Decode, Error};
1616

1717
/// The error message returned when `decode_all` fails.
1818
pub(crate) const DECODE_ALL_ERR_MSG: &str = "Input buffer has still data left after decoding!";
@@ -23,12 +23,11 @@ pub trait DecodeAll: Sized {
2323
/// Decode `Self` and consume all of the given input data.
2424
///
2525
/// If not all data is consumed, an error is returned.
26-
fn decode_all(input: &[u8]) -> Result<Self, Error>;
26+
fn decode_all(input: &mut &[u8]) -> Result<Self, Error>;
2727
}
2828

2929
impl<T: Decode> DecodeAll for T {
30-
fn decode_all(input: &[u8]) -> Result<Self, Error> {
31-
let input = &mut &input[..];
30+
fn decode_all(input: &mut &[u8]) -> Result<Self, Error> {
3231
let res = T::decode(input)?;
3332

3433
if input.is_empty() {
@@ -42,7 +41,7 @@ impl<T: Decode> DecodeAll for T {
4241
#[cfg(test)]
4342
mod tests {
4443
use super::*;
45-
use crate::{Encode, Input, Compact, EncodeLike};
44+
use crate::{Compact, Encode, EncodeLike, Input};
4645

4746
macro_rules! test_decode_all {
4847
(
@@ -51,13 +50,13 @@ mod tests {
5150
$(
5251
{
5352
let mut encoded = <$type as Encode>::encode(&$value);
54-
<$type>::decode_all(&encoded).expect(
53+
<$type>::decode_all(&mut encoded.as_slice()).expect(
5554
&format!("`{} => {}` decodes all!", stringify!($type), stringify!($value)),
5655
);
5756

5857
encoded.extend(&[1, 2, 3, 4, 5, 6]);
5958
assert_eq!(
60-
<$type>::decode_all(&encoded).unwrap_err().to_string(),
59+
<$type>::decode_all(&mut encoded.as_slice()).unwrap_err().to_string(),
6160
"Input buffer has still data left after decoding!",
6261
);
6362
}
@@ -86,13 +85,11 @@ mod tests {
8685

8786
impl Decode for TestStruct {
8887
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
89-
Ok(
90-
Self {
91-
data: Vec::<u32>::decode(input)?,
92-
other: u8::decode(input)?,
93-
compact: Compact::<u128>::decode(input)?,
94-
}
95-
)
88+
Ok(Self {
89+
data: Vec::<u32>::decode(input)?,
90+
other: u8::decode(input)?,
91+
compact: Compact::<u128>::decode(input)?,
92+
})
9693
}
9794
}
9895

src/depth_limit.rs

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,32 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use crate::{Error, Decode, Input};
15+
use crate::{Decode, Error, Input};
1616

1717
/// The error message returned when depth limit is reached.
1818
const DECODE_MAX_DEPTH_MSG: &str = "Maximum recursion depth reached when decoding";
1919

2020
/// Extension trait to [`Decode`] for decoding with a maximum recursion depth.
2121
pub trait DecodeLimit: Sized {
22-
/// Decode `Self` with the given maximum recursion depth.
22+
/// Decode `Self` with the given maximum recursion depth and advance `input` by the number of
23+
/// bytes consumed.
2324
///
2425
/// If `limit` is hit, an error is returned.
25-
fn decode_with_depth_limit(limit: u32, input: &[u8]) -> Result<Self, Error>;
26-
27-
/// Decode `Self` and advance `input` by the number of bytes consumed.
28-
///
29-
/// If `limit` is hit, an error is returned.
30-
fn decode_and_advance_with_depth_limit<I: Input>(limit: u32, input: &mut I) -> Result<Self, Error>;
26+
fn decode_with_depth_limit<I: Input>(limit: u32, input: &mut I) -> Result<Self, Error>;
3127

3228
/// Decode `Self` and consume all of the given input data.
3329
///
3430
/// If not all data is consumed or `limit` is hit, an error is returned.
35-
fn decode_all_with_depth_limit(limit: u32, input: &[u8]) -> Result<Self, Error>;
31+
fn decode_all_with_depth_limit(limit: u32, input: &mut &[u8]) -> Result<Self, Error>;
3632
}
3733

38-
3934
struct DepthTrackingInput<'a, I> {
4035
input: &'a mut I,
4136
depth: u32,
4237
max_depth: u32,
4338
}
4439

45-
impl<'a, I:Input> Input for DepthTrackingInput<'a, I> {
40+
impl<'a, I: Input> Input for DepthTrackingInput<'a, I> {
4641
fn remaining_len(&mut self) -> Result<Option<usize>, Error> {
4742
self.input.remaining_len()
4843
}
@@ -72,36 +67,18 @@ impl<'a, I:Input> Input for DepthTrackingInput<'a, I> {
7267
}
7368

7469
impl<T: Decode> DecodeLimit for T {
75-
fn decode_all_with_depth_limit(limit: u32, input: &[u8]) -> Result<Self, Error> {
76-
let mut input = DepthTrackingInput {
77-
input: &mut &input[..],
78-
depth: 0,
79-
max_depth: limit,
80-
};
81-
let res = T::decode(&mut input)?;
82-
83-
if input.input.is_empty() {
84-
Ok(res)
70+
fn decode_all_with_depth_limit(limit: u32, input: &mut &[u8]) -> Result<Self, Error> {
71+
let t = <Self as DecodeLimit>::decode_with_depth_limit(limit, input)?;
72+
73+
if input.is_empty() {
74+
Ok(t)
8575
} else {
8676
Err(crate::decode_all::DECODE_ALL_ERR_MSG.into())
8777
}
8878
}
8979

90-
fn decode_and_advance_with_depth_limit<I: Input>(limit: u32, input: &mut I) -> Result<Self, Error> {
91-
let mut input = DepthTrackingInput {
92-
input,
93-
depth: 0,
94-
max_depth: limit,
95-
};
96-
T::decode(&mut input)
97-
}
98-
99-
fn decode_with_depth_limit(limit: u32, input: &[u8]) -> Result<Self, Error> {
100-
let mut input = DepthTrackingInput {
101-
input: &mut &input[..],
102-
depth: 0,
103-
max_depth: limit,
104-
};
80+
fn decode_with_depth_limit<I: Input>(limit: u32, input: &mut I) -> Result<Self, Error> {
81+
let mut input = DepthTrackingInput { input, depth: 0, max_depth: limit };
10582
T::decode(&mut input)
10683
}
10784
}
@@ -117,19 +94,38 @@ mod tests {
11794
let nested: NestedVec = vec![vec![vec![vec![1]]]];
11895
let encoded = nested.encode();
11996

120-
let decoded = NestedVec::decode_with_depth_limit(3, &encoded).unwrap();
97+
let decoded = NestedVec::decode_with_depth_limit(3, &mut encoded.as_slice()).unwrap();
12198
assert_eq!(decoded, nested);
122-
assert!(NestedVec::decode_with_depth_limit(2, &encoded).is_err());
99+
assert!(NestedVec::decode_with_depth_limit(2, &mut encoded.as_slice()).is_err());
123100
}
124101

125102
#[test]
126-
fn decode_and_advance_works() {
103+
fn decode_limit_advances_input() {
127104
type NestedVec = Vec<Vec<Vec<Vec<u8>>>>;
128105
let nested: NestedVec = vec![vec![vec![vec![1]]]];
129-
let encoded = &mut &nested.encode()[..];
106+
let encoded = nested.encode();
107+
let encoded_slice = &mut encoded.as_slice();
130108

131-
let decoded = Vec::<u8>::decode_and_advance_with_depth_limit(1, encoded).unwrap();
109+
let decoded = Vec::<u8>::decode_with_depth_limit(1, encoded_slice).unwrap();
132110
assert_eq!(decoded, vec![4]);
133-
assert!(NestedVec::decode_with_depth_limit(3, encoded).is_err());
111+
assert!(NestedVec::decode_with_depth_limit(3, encoded_slice).is_err());
112+
}
113+
114+
#[test]
115+
fn decode_all_with_limit_advances_input() {
116+
type NestedVec = Vec<Vec<Vec<Vec<u8>>>>;
117+
let nested: NestedVec = vec![vec![vec![vec![1]]]];
118+
let mut encoded = NestedVec::encode(&nested);
119+
120+
let decoded = NestedVec::decode_all_with_depth_limit(3, &mut encoded.as_slice()).unwrap();
121+
assert_eq!(decoded, nested);
122+
123+
encoded.extend(&[1, 2, 3, 4, 5, 6]);
124+
assert_eq!(
125+
NestedVec::decode_all_with_depth_limit(3, &mut encoded.as_slice())
126+
.unwrap_err()
127+
.to_string(),
128+
"Input buffer has still data left after decoding!",
129+
);
134130
}
135131
}

0 commit comments

Comments
 (0)