tetsy_scale_codec/
decode_all.rs

1// Copyright 2017, 2018 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{Error, Decode};
16
17/// The error message returned when `decode_all` fails.
18pub(crate) const DECODE_ALL_ERR_MSG: &str = "Input buffer has still data left after decoding!";
19
20/// Extension trait to [`Decode`] that ensures that the given input data is consumed completly while
21/// decoding.
22pub trait DecodeAll: Sized {
23	/// Decode `Self` and consume all of the given input data.
24	///
25	/// If not all data is consumed, an error is returned.
26	fn decode_all(input: &[u8]) -> Result<Self, Error>;
27}
28
29impl<T: Decode> DecodeAll for T {
30	fn decode_all(input: &[u8]) -> Result<Self, Error> {
31		let input = &mut &input[..];
32		let res = T::decode(input)?;
33
34		if input.is_empty() {
35			Ok(res)
36		} else {
37			Err(DECODE_ALL_ERR_MSG.into())
38		}
39	}
40}
41
42#[cfg(test)]
43mod tests {
44	use super::*;
45	use crate::{Encode, Input, Compact, EncodeLike};
46
47	macro_rules! test_decode_all {
48		(
49			$( $type:ty => $value:expr; )*
50		) => {
51			$(
52				{
53					let mut encoded = <$type as Encode>::encode(&$value);
54					<$type>::decode_all(&encoded).expect(
55						&format!("`{} => {}` decodes all!", stringify!($type), stringify!($value)),
56					);
57
58					encoded.extend(&[1, 2, 3, 4, 5, 6]);
59					assert_eq!(
60						<$type>::decode_all(&encoded).unwrap_err().to_string(),
61						"Input buffer has still data left after decoding!",
62					);
63				}
64			)*
65		};
66	}
67
68	#[derive(Debug)]
69	struct TestStruct {
70		data: Vec<u32>,
71		other: u8,
72		compact: Compact<u128>,
73	}
74
75	impl EncodeLike for TestStruct {}
76
77	impl Encode for TestStruct {
78		fn encode(&self) -> Vec<u8> {
79			let mut res = Vec::new();
80			self.data.encode_to(&mut res);
81			self.other.encode_to(&mut res);
82			self.compact.encode_to(&mut res);
83			res
84		}
85	}
86
87	impl Decode for TestStruct {
88		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			)
96		}
97	}
98
99	#[test]
100	fn decode_all_works() {
101		test_decode_all! {
102			u8 => 120;
103			u16 => 30;
104			u32 => 1;
105			u64 => 2343545;
106			u128 => 34358394245459854;
107			Vec<u8> => vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
108			Vec<u32> => vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
109			Compact<u32> => Compact(32445);
110			Compact<u128> => Compact(34353454453545);
111			TestStruct => TestStruct { data: vec![1, 2, 4, 5, 6], other: 45, compact: Compact(123234545) };
112		}
113	}
114}