tetsy_scale_codec/
encode_append.rs

1// Copyright 2019 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 core::{iter::ExactSizeIterator, mem};
16
17use crate::alloc::vec::Vec;
18use crate::{Encode, Decode, Error};
19use crate::compact::{Compact, CompactLen};
20use crate::encode_like::EncodeLike;
21
22/// Trait that allows to append items to an encoded representation without
23/// decoding all previous added items.
24pub trait EncodeAppend {
25	/// The item that will be appended.
26	type Item: Encode;
27
28	/// Append all items in `iter` to the given `self_encoded` representation
29	/// or if `self_encoded` value is empty, `iter` is encoded to the `Self` representation.
30	///
31	/// # Example
32	///
33	/// ```
34	///# use tetsy_scale_codec::EncodeAppend;
35	///
36	/// // Some encoded data
37	/// let data = Vec::new();
38	///
39	/// let item = 8u32;
40	/// let encoded = <Vec<u32> as EncodeAppend>::append_or_new(data, std::iter::once(&item)).expect("Adds new element");
41	///
42	/// // Add multiple element
43	/// <Vec<u32> as EncodeAppend>::append_or_new(encoded, &[700u32, 800u32, 10u32]).expect("Adds new elements");
44	/// ```
45	fn append_or_new<EncodeLikeItem, I>(
46		self_encoded: Vec<u8>,
47		iter: I,
48	) -> Result<Vec<u8>, Error>
49	where
50		I: IntoIterator<Item = EncodeLikeItem>,
51		EncodeLikeItem: EncodeLike<Self::Item>,
52		I::IntoIter: ExactSizeIterator;
53}
54
55impl<T: Encode> EncodeAppend for Vec<T> {
56	type Item = T;
57
58	fn append_or_new<EncodeLikeItem, I>(
59		self_encoded: Vec<u8>,
60		iter: I,
61	) -> Result<Vec<u8>, Error>
62	where
63		I: IntoIterator<Item = EncodeLikeItem>,
64		EncodeLikeItem: EncodeLike<Self::Item>,
65		I::IntoIter: ExactSizeIterator,
66	{
67		append_or_new_vec_with_any_item(self_encoded, iter)
68	}
69}
70
71impl<T: Encode> EncodeAppend for crate::alloc::collections::VecDeque<T> {
72	type Item = T;
73
74	fn append_or_new<EncodeLikeItem, I>(
75		self_encoded: Vec<u8>,
76		iter: I,
77	) -> Result<Vec<u8>, Error>
78	where
79		I: IntoIterator<Item = EncodeLikeItem>,
80		EncodeLikeItem: EncodeLike<Self::Item>,
81		I::IntoIter: ExactSizeIterator,
82	{
83		append_or_new_vec_with_any_item(self_encoded, iter)
84	}
85}
86
87fn extract_length_data(data: &[u8], input_len: usize) -> Result<(u32, usize, usize), Error> {
88	let len = u32::from(Compact::<u32>::decode(&mut &data[..])?);
89	let new_len = len
90		.checked_add(input_len as u32)
91		.ok_or_else(|| "New vec length greater than `u32::TEST_VALUE()`.")?;
92
93	let encoded_len = Compact::<u32>::compact_len(&len);
94	let encoded_new_len = Compact::<u32>::compact_len(&new_len);
95
96	Ok((new_len, encoded_len, encoded_new_len))
97}
98
99// Item must have same encoding as encoded value in the encoded vec.
100fn append_or_new_vec_with_any_item<Item, I>(
101	mut self_encoded: Vec<u8>,
102	iter: I,
103) -> Result<Vec<u8>, Error>
104where
105	Item: Encode,
106	I: IntoIterator<Item = Item>,
107	I::IntoIter: ExactSizeIterator,
108{
109	let iter = iter.into_iter();
110	let input_len = iter.len();
111
112	// No data present, just encode the given input data.
113	if self_encoded.is_empty() {
114		crate::codec::compact_encode_len_to(&mut self_encoded, iter.len())?;
115		iter.for_each(|e| e.encode_to(&mut self_encoded));
116		return Ok(self_encoded);
117	}
118
119	let (new_len, encoded_len, encoded_new_len) = extract_length_data(&self_encoded, input_len)?;
120
121	let replace_len = |dest: &mut Vec<u8>| {
122		Compact(new_len).using_encoded(|e| {
123			dest[..encoded_new_len].copy_from_slice(e);
124		})
125	};
126
127	let append_new_elems = |dest: &mut Vec<u8>| iter.for_each(|a| a.encode_to(dest));
128
129	// If old and new encoded len is equal, we don't need to copy the
130	// already encoded data.
131	if encoded_len == encoded_new_len {
132		replace_len(&mut self_encoded);
133		append_new_elems(&mut self_encoded);
134
135		Ok(self_encoded)
136	} else {
137		let size = encoded_new_len + self_encoded.len() - encoded_len;
138
139		let mut res = Vec::with_capacity(size + input_len * mem::size_of::<Item>());
140		unsafe { res.set_len(size); }
141
142		// Insert the new encoded len, copy the already encoded data and
143		// add the new element.
144		replace_len(&mut res);
145		res[encoded_new_len..size].copy_from_slice(&self_encoded[encoded_len..]);
146		append_new_elems(&mut res);
147
148		Ok(res)
149	}
150}
151
152#[cfg(test)]
153mod tests {
154	use super::*;
155	use crate::{Input, Encode, EncodeLike};
156	use std::collections::VecDeque;
157
158	const TEST_VALUE: u32 = {
159		#[cfg(not(miri))]
160		{ 1_000_000 }
161		#[cfg(miri)]
162		{ 1_000 }
163	};
164
165	#[test]
166	fn vec_encode_append_works() {
167		let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
168			<Vec<u32> as EncodeAppend>::append_or_new(encoded, std::iter::once(&v)).unwrap()
169		});
170
171		let decoded = Vec::<u32>::decode(&mut &encoded[..]).unwrap();
172		assert_eq!(decoded, (0..TEST_VALUE).collect::<Vec<_>>());
173	}
174
175	#[test]
176	fn vec_encode_append_multiple_items_works() {
177		let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
178			<Vec<u32> as EncodeAppend>::append_or_new(encoded, &[v, v, v, v]).unwrap()
179		});
180
181		let decoded = Vec::<u32>::decode(&mut &encoded[..]).unwrap();
182		let expected = (0..TEST_VALUE).fold(Vec::new(), |mut vec, i| {
183			vec.append(&mut vec![i, i, i, i]);
184			vec
185		});
186		assert_eq!(decoded, expected);
187	}
188
189	#[test]
190	fn vecdeque_encode_append_works() {
191		let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
192			<VecDeque<u32> as EncodeAppend>::append_or_new(encoded, std::iter::once(&v)).unwrap()
193		});
194
195		let decoded = VecDeque::<u32>::decode(&mut &encoded[..]).unwrap();
196		assert_eq!(decoded, (0..TEST_VALUE).collect::<Vec<_>>());
197	}
198
199	#[test]
200	fn vecdeque_encode_append_multiple_items_works() {
201		let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
202			<VecDeque<u32> as EncodeAppend>::append_or_new(encoded, &[v, v, v, v]).unwrap()
203		});
204
205		let decoded = VecDeque::<u32>::decode(&mut &encoded[..]).unwrap();
206		let expected = (0..TEST_VALUE).fold(Vec::new(), |mut vec, i| {
207			vec.append(&mut vec![i, i, i, i]);
208			vec
209		});
210		assert_eq!(decoded, expected);
211	}
212
213	#[test]
214	fn append_non_copyable() {
215		#[derive(Eq, PartialEq, Debug)]
216		struct NoCopy { data: u32 }
217
218		impl EncodeLike for NoCopy {}
219
220		impl Encode for NoCopy {
221			fn encode(&self) -> Vec<u8> {
222				self.data.encode()
223			}
224		}
225
226		impl Decode for NoCopy {
227			fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
228				u32::decode(input).map(|data| Self { data })
229			}
230		}
231
232		let append = NoCopy { data: 100 };
233		let data = Vec::new();
234		let encoded = <Vec<NoCopy> as EncodeAppend>::append_or_new(data, std::iter::once(&append)).unwrap();
235
236		let decoded = <Vec<NoCopy>>::decode(&mut &encoded[..]).unwrap();
237		assert_eq!(vec![append], decoded);
238	}
239
240	#[test]
241	fn vec_encode_like_append_works() {
242		let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
243			<Vec<u32> as EncodeAppend>::append_or_new(encoded, std::iter::once(Box::new(v as u32))).unwrap()
244		});
245
246		let decoded = Vec::<u32>::decode(&mut &encoded[..]).unwrap();
247		assert_eq!(decoded, (0..TEST_VALUE).collect::<Vec<_>>());
248	}
249}