jam_types/
fixed_vec.rs

1use super::*;
2use bounded_collections::Get;
3use core::fmt;
4use scale::{decode_vec_with_len, ConstEncodedLen, Error as DecodeError, Output};
5
6/// Trait for vector types which have a bounded length allowing element-wise transformation.
7pub trait BoundedMap<T, N: Get<u32>> {
8	/// Element-wise transformation of items using the given function.
9	///
10	/// - `f`: The transformation function.
11	///
12	/// Returns a new instance with all elements transformed using the function `f`.
13	fn map<U>(self, f: impl FnMut(T) -> U) -> BoundedVec<U, N>;
14	/// Element-wise transformation of item-references using the given function.
15	///
16	/// - `f`: The transformation function.
17	///
18	/// Returns a new instance with all element-references transformed using the function `f`.
19	fn map_ref<U>(&self, f: impl FnMut(&T) -> U) -> BoundedVec<U, N>;
20	/// Fallible element-wise transformation of items using the given function.
21	///
22	/// - `f`: The transformation function.
23	///
24	/// Returns a new instance with all elements transformed using the function `f`, or
25	/// `Err` if any invocation of `f` resulted in error.
26	fn try_map<U, E>(self, f: impl FnMut(T) -> Result<U, E>) -> Result<BoundedVec<U, N>, E>;
27	/// Fallible element-wise transformation of item-references using the given function.
28	///
29	/// - `f`: The transformation function.
30	///
31	/// Returns a new instance with all element-references transformed using the function `f`, or
32	/// `Err` if any invocation of `f` resulted in error.
33	fn try_map_ref<U, E>(&self, f: impl FnMut(&T) -> Result<U, E>) -> Result<BoundedVec<U, N>, E>;
34}
35impl<T, N: Get<u32>> BoundedMap<T, N> for BoundedVec<T, N> {
36	fn map<U>(self, f: impl FnMut(T) -> U) -> BoundedVec<U, N> {
37		BoundedVec::truncate_from(self.into_iter().map(f).collect::<Vec<_>>())
38	}
39	fn map_ref<U>(&self, f: impl FnMut(&T) -> U) -> BoundedVec<U, N> {
40		BoundedVec::truncate_from(self.iter().map(f).collect::<Vec<_>>())
41	}
42	fn try_map<U, E>(self, f: impl FnMut(T) -> Result<U, E>) -> Result<BoundedVec<U, N>, E> {
43		self.into_iter()
44			.map(f)
45			.collect::<Result<Vec<_>, E>>()
46			.map(BoundedVec::truncate_from)
47	}
48	fn try_map_ref<U, E>(&self, f: impl FnMut(&T) -> Result<U, E>) -> Result<BoundedVec<U, N>, E> {
49		self.iter().map(f).collect::<Result<Vec<_>, E>>().map(BoundedVec::truncate_from)
50	}
51}
52
53/// Vector type with a fixed length.
54///
55/// Can be used similarly to an array but which stores its elements on the heap.
56pub struct FixedVec<T, N: Get<u32>>(BoundedVec<T, N>);
57impl<T, N: Get<u32>> FixedVec<T, N> {
58	pub fn new(t: T) -> Self
59	where
60		T: Clone,
61	{
62		Self::from_fn(|_| t.clone())
63	}
64	pub fn padded(t: &[T]) -> Self
65	where
66		T: Default + Clone,
67	{
68		Self::from_fn(|i| t.get(i).cloned().unwrap_or_default())
69	}
70	pub fn from_fn(f: impl FnMut(usize) -> T) -> Self {
71		Self(BoundedVec::truncate_from((0..N::get() as usize).map(f).collect::<Vec<T>>()))
72	}
73	pub fn get(&self, i: usize) -> Option<&T> {
74		if i < N::get() as usize {
75			Some(&self.0[i])
76		} else {
77			None
78		}
79	}
80	pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
81		if i < N::get() as usize {
82			Some(&mut self.0[i])
83		} else {
84			None
85		}
86	}
87	pub fn len(&self) -> usize {
88		N::get() as usize
89	}
90	pub fn is_empty(&self) -> bool {
91		N::get() == 0
92	}
93	pub fn iter(&self) -> core::slice::Iter<T> {
94		self.0.iter()
95	}
96	pub fn iter_mut(&mut self) -> core::slice::IterMut<T> {
97		self.0.iter_mut()
98	}
99	pub fn map<U>(self, f: impl FnMut(T) -> U) -> FixedVec<U, N> {
100		FixedVec(BoundedVec::truncate_from(self.0.into_iter().map(f).collect::<Vec<_>>()))
101	}
102	pub fn map_ref<U>(&self, f: impl FnMut(&T) -> U) -> FixedVec<U, N> {
103		FixedVec(BoundedVec::truncate_from(self.0.iter().map(f).collect::<Vec<_>>()))
104	}
105	pub fn to_bounded(self) -> BoundedVec<T, N> {
106		self.0
107	}
108	pub fn to_vec(self) -> Vec<T> {
109		self.0.into()
110	}
111	pub fn into_vec(self) -> Vec<T> {
112		self.0.into()
113	}
114	pub fn truncate_into_vec(self, len: usize) -> Vec<T> {
115		let mut v = self.into_vec();
116		v.truncate(len);
117		v
118	}
119	pub fn slide(&mut self, index: usize, insert_at: usize) {
120		self.0.slide(index, insert_at);
121	}
122	pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> Result<Option<T>, T> {
123		self.0.force_insert_keep_left(index, element)
124	}
125	pub fn force_insert_keep_right(&mut self, index: usize, element: T) -> Result<Option<T>, T> {
126		self.0.force_insert_keep_right(index, element)
127	}
128	pub fn force_push(&mut self, element: T) {
129		self.0.force_push(element);
130	}
131	pub fn swap(&mut self, a: usize, b: usize) {
132		self.0.as_mut().swap(a, b);
133	}
134	pub fn as_slice(&self) -> &[T] {
135		self.0.as_slice()
136	}
137	pub fn as_mut_slice(&mut self) -> &mut [T] {
138		self.0.as_mut()
139	}
140	pub fn as_ptr(&self) -> *const T {
141		self.0.as_ptr()
142	}
143	pub fn as_mut_ptr(&mut self) -> *mut T {
144		self.0.as_mut().as_mut_ptr()
145	}
146}
147
148impl<T: Encode, N: Get<u32>> Encode for FixedVec<T, N> {
149	fn size_hint(&self) -> usize {
150		self.0.size_hint() - 1
151	}
152	fn encode_to<D: Output + ?Sized>(&self, dest: &mut D) {
153		for t in self.0.iter() {
154			t.encode_to(dest);
155		}
156	}
157}
158
159impl<T: fmt::Debug, N: Get<u32>> fmt::Debug for FixedVec<T, N> {
160	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161		match self.0.len() {
162			0 => write!(f, "[]"),
163			_ => {
164				write!(f, "[{:?}", self.0[0])?;
165				for i in 1..self.len() {
166					write!(f, ", {:?}", self.0[i])?;
167				}
168				write!(f, "]")
169			},
170		}
171	}
172}
173
174impl<T: ConstEncodedLen, N: Get<u32>> scale::ConstEncodedLen for FixedVec<T, N> {}
175
176impl<N: Get<u32>> fmt::Display for FixedVec<u8, N> {
177	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178		let suffix = self.iter().rev().take_while(|&&x| x == 0).count();
179		let body = &self.0[..self.len() - suffix];
180		if !body.is_empty() {
181			if body.iter().all(|&x| (32..=127).contains(&x)) {
182				f.write_fmt(format_args!(
183					"\"{}\"",
184					core::str::from_utf8(body).expect("ASCII; qed")
185				))?;
186			}
187			if body.len() > 32 {
188				f.write_fmt(format_args!(
189					"0x{}..{}",
190					hex::hex(&body[..8]),
191					hex::hex(&body[body.len() - 4..])
192				))?;
193			} else {
194				f.write_fmt(format_args!("0x{}", hex::hex(body)))?;
195			}
196		}
197		if suffix != 0 {
198			f.write_fmt(format_args!("{}{suffix}*0", if !body.is_empty() { "+" } else { "" }))?;
199		}
200		Ok(())
201	}
202}
203
204impl<T: Decode, N: Get<u32>> Decode for FixedVec<T, N> {
205	fn decode<I: scale::Input>(input: &mut I) -> Result<Self, DecodeError> {
206		Ok(Self(BoundedVec::truncate_from(decode_vec_with_len(input, N::get() as usize)?)))
207	}
208}
209
210impl<T: MaxEncodedLen, N: Get<u32>> MaxEncodedLen for FixedVec<T, N> {
211	fn max_encoded_len() -> usize {
212		T::max_encoded_len() * N::get() as usize
213	}
214}
215
216impl<T: Clone, N: Get<u32>> Clone for FixedVec<T, N> {
217	fn clone(&self) -> Self {
218		Self(self.0.clone())
219	}
220}
221impl<T: Eq, N: Get<u32>> Eq for FixedVec<T, N> where T: Eq {}
222impl<T: PartialEq, N: Get<u32>> PartialEq for FixedVec<T, N> {
223	fn eq(&self, other: &Self) -> bool {
224		self.0[..] == other.0[..]
225	}
226}
227impl<T: Default, N: Get<u32>> Default for FixedVec<T, N> {
228	fn default() -> Self {
229		Self::from_fn(|_| T::default())
230	}
231}
232impl<T, N: Get<u32>> AsRef<[T]> for FixedVec<T, N> {
233	fn as_ref(&self) -> &[T] {
234		&self.0[..]
235	}
236}
237impl<T, N: Get<u32>> AsMut<[T]> for FixedVec<T, N> {
238	fn as_mut(&mut self) -> &mut [T] {
239		&mut self.0[..]
240	}
241}
242impl<T, N: Get<u32>> core::ops::Index<usize> for FixedVec<T, N> {
243	type Output = T;
244	fn index(&self, i: usize) -> &T {
245		&self.0[i]
246	}
247}
248impl<T, N: Get<u32>> core::ops::IndexMut<usize> for FixedVec<T, N> {
249	fn index_mut(&mut self, i: usize) -> &mut T {
250		&mut self.0[i]
251	}
252}
253impl<T, N: Get<u32>> core::ops::Index<core::ops::Range<usize>> for FixedVec<T, N> {
254	type Output = [T];
255
256	fn index(&self, index: core::ops::Range<usize>) -> &Self::Output {
257		&self.0[index]
258	}
259}
260impl<T, N: Get<u32>> core::ops::IndexMut<core::ops::Range<usize>> for FixedVec<T, N> {
261	fn index_mut(&mut self, index: core::ops::Range<usize>) -> &mut Self::Output {
262		&mut self.0[index]
263	}
264}
265impl<T, N: Get<u32>> core::ops::Index<core::ops::RangeFull> for FixedVec<T, N> {
266	type Output = [T];
267
268	fn index(&self, index: core::ops::RangeFull) -> &Self::Output {
269		&self.0[index]
270	}
271}
272impl<T, N: Get<u32>> core::ops::IndexMut<core::ops::RangeFull> for FixedVec<T, N> {
273	fn index_mut(&mut self, index: core::ops::RangeFull) -> &mut Self::Output {
274		&mut self.0[index]
275	}
276}
277impl<T, N: Get<u32>> From<FixedVec<T, N>> for Vec<T> {
278	fn from(s: FixedVec<T, N>) -> Vec<T> {
279		s.to_vec()
280	}
281}
282impl<T, N: Get<u32>> TryFrom<Vec<T>> for FixedVec<T, N> {
283	type Error = ();
284	fn try_from(v: Vec<T>) -> Result<Self, ()> {
285		if v.len() != N::get() as usize {
286			panic!("Invalid length");
287		}
288		Ok(Self(BoundedVec::truncate_from(v)))
289	}
290}
291impl<T, N: Get<u32>> From<FixedVec<T, N>> for BoundedVec<T, N> {
292	fn from(s: FixedVec<T, N>) -> BoundedVec<T, N> {
293		s.0
294	}
295}
296impl<T, N: Get<u32>> TryFrom<BoundedVec<T, N>> for FixedVec<T, N> {
297	type Error = ();
298	fn try_from(v: BoundedVec<T, N>) -> Result<Self, ()> {
299		if v.len() != N::get() as usize {
300			return Err(())
301		}
302		Ok(Self(v))
303	}
304}
305impl<'a, T: Clone, N: Get<u32>> TryFrom<&'a [T]> for FixedVec<T, N> {
306	type Error = ();
307	fn try_from(v: &'a [T]) -> Result<Self, ()> {
308		if v.len() != N::get() as usize {
309			return Err(())
310		}
311		Ok(Self(BoundedVec::truncate_from(v.to_vec())))
312	}
313}