parity_scale_codec/
encode_append.rs1use core::iter::ExactSizeIterator;
16
17use crate::{
18 alloc::vec::Vec,
19 compact::{Compact, CompactLen},
20 encode_like::EncodeLike,
21 Decode, Encode, Error,
22};
23
24pub trait EncodeAppend {
27 type Item: Encode;
29
30 fn append_or_new<EncodeLikeItem, I>(self_encoded: Vec<u8>, iter: I) -> Result<Vec<u8>, Error>
48 where
49 I: IntoIterator<Item = EncodeLikeItem>,
50 EncodeLikeItem: EncodeLike<Self::Item>,
51 I::IntoIter: ExactSizeIterator;
52}
53
54impl<T: Encode> EncodeAppend for Vec<T> {
55 type Item = T;
56
57 fn append_or_new<EncodeLikeItem, I>(self_encoded: Vec<u8>, iter: I) -> Result<Vec<u8>, Error>
58 where
59 I: IntoIterator<Item = EncodeLikeItem>,
60 EncodeLikeItem: EncodeLike<Self::Item>,
61 I::IntoIter: ExactSizeIterator,
62 {
63 append_or_new_impl(self_encoded, iter)
64 }
65}
66
67impl<T: Encode> EncodeAppend for crate::alloc::collections::VecDeque<T> {
68 type Item = T;
69
70 fn append_or_new<EncodeLikeItem, I>(self_encoded: Vec<u8>, iter: I) -> Result<Vec<u8>, Error>
71 where
72 I: IntoIterator<Item = EncodeLikeItem>,
73 EncodeLikeItem: EncodeLike<Self::Item>,
74 I::IntoIter: ExactSizeIterator,
75 {
76 append_or_new_impl(self_encoded, iter)
77 }
78}
79
80fn append_or_new_impl<Item, I>(mut vec: Vec<u8>, iter: I) -> Result<Vec<u8>, Error>
84where
85 Item: Encode,
86 I: IntoIterator<Item = Item>,
87 I::IntoIter: ExactSizeIterator,
88{
89 let iter = iter.into_iter();
90 let items_to_append = iter.len();
91
92 if vec.is_empty() {
93 crate::codec::compact_encode_len_to(&mut vec, items_to_append)?;
94 } else {
95 let old_item_count = u32::from(Compact::<u32>::decode(&mut &vec[..])?);
96 let new_item_count = old_item_count
97 .checked_add(items_to_append as u32)
98 .ok_or("cannot append new items into a SCALE-encoded vector: length overflow due to too many items")?;
99
100 let old_item_count_encoded_bytesize = Compact::<u32>::compact_len(&old_item_count);
101 let new_item_count_encoded_bytesize = Compact::<u32>::compact_len(&new_item_count);
102
103 if old_item_count_encoded_bytesize == new_item_count_encoded_bytesize {
104 Compact(new_item_count).using_encoded(|length_encoded| {
107 vec[..old_item_count_encoded_bytesize].copy_from_slice(length_encoded)
108 });
109 } else {
110 let new_capacity = vec.len().checked_mul(2)
119 .ok_or("cannot append new items into a SCALE-encoded vector: new vector won't fit in memory")?;
120 let mut new_vec = Vec::with_capacity(new_capacity);
121
122 crate::codec::compact_encode_len_to(&mut new_vec, new_item_count as usize)?;
123 new_vec.extend_from_slice(&vec[old_item_count_encoded_bytesize..]);
124 vec = new_vec;
125 }
126 }
127
128 iter.for_each(|e| e.encode_to(&mut vec));
130 Ok(vec)
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use crate::{Encode, EncodeLike, Input};
137 use std::collections::VecDeque;
138
139 const TEST_VALUE: u32 = {
140 #[cfg(not(miri))]
141 {
142 1_000_000
143 }
144 #[cfg(miri)]
145 {
146 1_000
147 }
148 };
149
150 #[test]
151 fn vec_encode_append_works() {
152 let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
153 <Vec<u32> as EncodeAppend>::append_or_new(encoded, std::iter::once(&v)).unwrap()
154 });
155
156 let decoded = Vec::<u32>::decode(&mut &encoded[..]).unwrap();
157 assert_eq!(decoded, (0..TEST_VALUE).collect::<Vec<_>>());
158 }
159
160 #[test]
161 fn vec_encode_append_multiple_items_works() {
162 let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
163 <Vec<u32> as EncodeAppend>::append_or_new(encoded, [v, v, v, v]).unwrap()
164 });
165
166 let decoded = Vec::<u32>::decode(&mut &encoded[..]).unwrap();
167 let expected = (0..TEST_VALUE).fold(Vec::new(), |mut vec, i| {
168 vec.append(&mut vec![i, i, i, i]);
169 vec
170 });
171 assert_eq!(decoded, expected);
172 }
173
174 #[test]
175 fn vecdeque_encode_append_works() {
176 let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
177 <VecDeque<u32> as EncodeAppend>::append_or_new(encoded, std::iter::once(&v)).unwrap()
178 });
179
180 let decoded = VecDeque::<u32>::decode(&mut &encoded[..]).unwrap();
181 assert_eq!(decoded, (0..TEST_VALUE).collect::<Vec<_>>());
182 }
183
184 #[test]
185 fn vecdeque_encode_append_multiple_items_works() {
186 let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
187 <VecDeque<u32> as EncodeAppend>::append_or_new(encoded, [v, v, v, v]).unwrap()
188 });
189
190 let decoded = VecDeque::<u32>::decode(&mut &encoded[..]).unwrap();
191 let expected = (0..TEST_VALUE).fold(Vec::new(), |mut vec, i| {
192 vec.append(&mut vec![i, i, i, i]);
193 vec
194 });
195 assert_eq!(decoded, expected);
196 }
197
198 #[test]
199 fn append_non_copyable() {
200 #[derive(Eq, PartialEq, Debug)]
201 struct NoCopy {
202 data: u32,
203 }
204
205 impl EncodeLike for NoCopy {}
206
207 impl Encode for NoCopy {
208 fn encode(&self) -> Vec<u8> {
209 self.data.encode()
210 }
211 }
212
213 impl Decode for NoCopy {
214 fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
215 u32::decode(input).map(|data| Self { data })
216 }
217 }
218
219 let append = NoCopy { data: 100 };
220 let data = Vec::new();
221 let encoded =
222 <Vec<NoCopy> as EncodeAppend>::append_or_new(data, std::iter::once(&append)).unwrap();
223
224 let decoded = <Vec<NoCopy>>::decode(&mut &encoded[..]).unwrap();
225 assert_eq!(vec![append], decoded);
226 }
227
228 #[test]
229 fn vec_encode_like_append_works() {
230 let encoded = (0..TEST_VALUE).fold(Vec::new(), |encoded, v| {
231 <Vec<u32> as EncodeAppend>::append_or_new(encoded, std::iter::once(Box::new(v)))
232 .unwrap()
233 });
234
235 let decoded = Vec::<u32>::decode(&mut &encoded[..]).unwrap();
236 assert_eq!(decoded, (0..TEST_VALUE).collect::<Vec<_>>());
237 }
238}