Skip to main content

jam_types/
fixed_vec.rs

1use super::*;
2use bounded_collections::Get;
3use codec::{ConstEncodedLen, Error as DecodeError, Output, decode_vec_with_len};
4use core::fmt;
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}
35
36impl<T, N: Get<u32>> BoundedMap<T, N> for BoundedVec<T, N> {
37	fn map<U>(self, f: impl FnMut(T) -> U) -> BoundedVec<U, N> {
38		BoundedVec::truncate_from(self.into_iter().map(f).collect::<Vec<_>>())
39	}
40	fn map_ref<U>(&self, f: impl FnMut(&T) -> U) -> BoundedVec<U, N> {
41		BoundedVec::truncate_from(self.iter().map(f).collect::<Vec<_>>())
42	}
43	fn try_map<U, E>(self, f: impl FnMut(T) -> Result<U, E>) -> Result<BoundedVec<U, N>, E> {
44		self.into_iter()
45			.map(f)
46			.collect::<Result<Vec<_>, E>>()
47			.map(BoundedVec::truncate_from)
48	}
49	fn try_map_ref<U, E>(&self, f: impl FnMut(&T) -> Result<U, E>) -> Result<BoundedVec<U, N>, E> {
50		self.iter().map(f).collect::<Result<Vec<_>, E>>().map(BoundedVec::truncate_from)
51	}
52}
53
54/// Constructor for bounded vectors built from an index function.
55pub trait BoundedFromFn<T, N: Get<u32>>: Sized {
56	/// Build a vector of `len` elements, where element `i` is `f(i)`.
57	///
58	/// Panics if `len` exceeds the bound.
59	fn from_fn(len: usize, f: impl FnMut(usize) -> T) -> Self;
60
61	/// Build a vector filled up to the bound, where element `i` is `f(i)`.
62	fn from_fn_fill(f: impl FnMut(usize) -> T) -> Self {
63		Self::from_fn(N::get() as usize, f)
64	}
65
66	/// Build a vector filled up to the bound with default elements.
67	fn default_fill() -> Self
68	where
69		T: Default,
70	{
71		Self::from_fn_fill(|_| T::default())
72	}
73}
74impl<T, N: Get<u32>> BoundedFromFn<T, N> for BoundedVec<T, N> {
75	fn from_fn(len: usize, f: impl FnMut(usize) -> T) -> Self {
76		assert!(len <= N::get() as usize, "`from_fn` length {len} exceeds bound {}", N::get());
77		Self::truncate_from((0..len).map(f).collect())
78	}
79}
80
81/// Vector type with a fixed length.
82///
83/// Can be used similarly to an array but which stores its elements on the heap.
84pub struct FixedVec<T, N: Get<u32>>(BoundedVec<T, N>);
85impl<T, N: Get<u32>> FixedVec<T, N> {
86	pub fn new(t: T) -> Self
87	where
88		T: Clone,
89	{
90		Self::from_fn(|_| t.clone())
91	}
92	pub fn padded(t: &[T]) -> Self
93	where
94		T: Default + Clone,
95	{
96		Self::from_fn(|i| t.get(i).cloned().unwrap_or_default())
97	}
98	pub fn from_fn(f: impl FnMut(usize) -> T) -> Self {
99		Self(BoundedVec::truncate_from((0..N::get() as usize).map(f).collect::<Vec<T>>()))
100	}
101	pub fn get(&self, i: usize) -> Option<&T> {
102		if i < N::get() as usize { Some(&self.0[i]) } else { None }
103	}
104	pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
105		if i < N::get() as usize { Some(&mut self.0[i]) } else { None }
106	}
107	pub fn len(&self) -> usize {
108		N::get() as usize
109	}
110	pub fn is_empty(&self) -> bool {
111		N::get() == 0
112	}
113	pub fn iter(&self) -> core::slice::Iter<'_, T> {
114		self.0.iter()
115	}
116	pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
117		self.0.iter_mut()
118	}
119	pub fn map<U>(self, f: impl FnMut(T) -> U) -> FixedVec<U, N> {
120		FixedVec(BoundedVec::truncate_from(self.0.into_iter().map(f).collect::<Vec<_>>()))
121	}
122	pub fn map_ref<U>(&self, f: impl FnMut(&T) -> U) -> FixedVec<U, N> {
123		FixedVec(BoundedVec::truncate_from(self.0.iter().map(f).collect::<Vec<_>>()))
124	}
125	pub fn to_bounded(self) -> BoundedVec<T, N> {
126		self.0
127	}
128	pub fn to_vec(&self) -> Vec<T>
129	where
130		T: Clone,
131	{
132		self.0.to_vec()
133	}
134	pub fn into_vec(self) -> Vec<T> {
135		self.0.into()
136	}
137	pub fn truncate_into_vec(self, len: usize) -> Vec<T> {
138		let mut v = self.into_vec();
139		v.truncate(len);
140		v
141	}
142	pub fn slide(&mut self, index: usize, insert_at: usize) {
143		self.0.slide(index, insert_at);
144	}
145	pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> Result<Option<T>, T> {
146		self.0.force_insert_keep_left(index, element)
147	}
148	pub fn force_insert_keep_right(&mut self, index: usize, element: T) -> Result<Option<T>, T> {
149		self.0.force_insert_keep_right(index, element)
150	}
151	pub fn force_push(&mut self, element: T) {
152		self.0.force_push(element);
153	}
154	pub fn swap(&mut self, a: usize, b: usize) {
155		self.0.as_mut().swap(a, b);
156	}
157	pub fn as_slice(&self) -> &[T] {
158		self.0.as_slice()
159	}
160	pub fn as_mut_slice(&mut self) -> &mut [T] {
161		self.0.as_mut()
162	}
163	pub fn as_ptr(&self) -> *const T {
164		self.0.as_ptr()
165	}
166	pub fn as_mut_ptr(&mut self) -> *mut T {
167		self.0.as_mut().as_mut_ptr()
168	}
169}
170
171impl<T: Encode, N: Get<u32>> Encode for FixedVec<T, N> {
172	fn size_hint(&self) -> usize {
173		self.0.size_hint() - 1
174	}
175	fn encode_to<D: Output + ?Sized>(&self, dest: &mut D) {
176		for t in self.0.iter() {
177			t.encode_to(dest);
178		}
179	}
180}
181
182impl<T: fmt::Debug, N: Get<u32>> fmt::Debug for FixedVec<T, N> {
183	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184		match self.0.len() {
185			0 => write!(f, "[]"),
186			_ => {
187				write!(f, "[{:?}", self.0[0])?;
188				for i in 1..self.len() {
189					write!(f, ", {:?}", self.0[i])?;
190				}
191				write!(f, "]")
192			},
193		}
194	}
195}
196
197impl<T: ConstEncodedLen, N: Get<u32>> codec::ConstEncodedLen for FixedVec<T, N> {}
198
199impl<N: Get<u32>> fmt::Display for FixedVec<u8, N> {
200	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201		let suffix = self.iter().rev().take_while(|&&x| x == 0).count();
202		let body = &self.0[..self.len() - suffix];
203		if !body.is_empty() {
204			if body.iter().all(|&x| (32..=127).contains(&x)) {
205				f.write_fmt(format_args!(
206					"\"{}\"",
207					core::str::from_utf8(body).expect("ASCII; qed")
208				))?;
209			}
210			if body.len() > 32 {
211				f.write_fmt(format_args!(
212					"0x{}..{}",
213					hex::hex(&body[..8]),
214					hex::hex(&body[body.len() - 4..])
215				))?;
216			} else {
217				f.write_fmt(format_args!("0x{}", hex::hex(body)))?;
218			}
219		}
220		if suffix != 0 {
221			f.write_fmt(format_args!("{}{suffix}*0", if !body.is_empty() { "+" } else { "" }))?;
222		}
223		Ok(())
224	}
225}
226
227impl<T: Decode, N: Get<u32>> Decode for FixedVec<T, N> {
228	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, DecodeError> {
229		Ok(Self(BoundedVec::truncate_from(decode_vec_with_len(input, N::get() as usize)?)))
230	}
231}
232
233impl<T: MaxEncodedLen, N: Get<u32>> MaxEncodedLen for FixedVec<T, N> {
234	fn max_encoded_len() -> usize {
235		T::max_encoded_len() * N::get() as usize
236	}
237}
238
239impl<T: Clone, N: Get<u32>> Clone for FixedVec<T, N> {
240	fn clone(&self) -> Self {
241		Self(self.0.clone())
242	}
243}
244impl<T: Eq, N: Get<u32>> Eq for FixedVec<T, N> where T: Eq {}
245impl<T: PartialEq, N: Get<u32>> PartialEq for FixedVec<T, N> {
246	fn eq(&self, other: &Self) -> bool {
247		self.0[..] == other.0[..]
248	}
249}
250impl<T: Default, N: Get<u32>> Default for FixedVec<T, N> {
251	fn default() -> Self {
252		Self::from_fn(|_| T::default())
253	}
254}
255impl<T, N: Get<u32>> AsRef<[T]> for FixedVec<T, N> {
256	fn as_ref(&self) -> &[T] {
257		&self.0[..]
258	}
259}
260impl<T, N: Get<u32>> AsMut<[T]> for FixedVec<T, N> {
261	fn as_mut(&mut self) -> &mut [T] {
262		&mut self.0[..]
263	}
264}
265impl<T, N: Get<u32>> core::ops::Index<usize> for FixedVec<T, N> {
266	type Output = T;
267	fn index(&self, i: usize) -> &T {
268		&self.0[i]
269	}
270}
271impl<T, N: Get<u32>> core::ops::IndexMut<usize> for FixedVec<T, N> {
272	fn index_mut(&mut self, i: usize) -> &mut T {
273		&mut self.0[i]
274	}
275}
276impl<T, N: Get<u32>> core::ops::Index<core::ops::Range<usize>> for FixedVec<T, N> {
277	type Output = [T];
278
279	fn index(&self, index: core::ops::Range<usize>) -> &Self::Output {
280		&self.0[index]
281	}
282}
283impl<T, N: Get<u32>> core::ops::IndexMut<core::ops::Range<usize>> for FixedVec<T, N> {
284	fn index_mut(&mut self, index: core::ops::Range<usize>) -> &mut Self::Output {
285		&mut self.0[index]
286	}
287}
288impl<T, N: Get<u32>> core::ops::Index<core::ops::RangeFull> for FixedVec<T, N> {
289	type Output = [T];
290
291	fn index(&self, index: core::ops::RangeFull) -> &Self::Output {
292		&self.0[index]
293	}
294}
295impl<T, N: Get<u32>> core::ops::IndexMut<core::ops::RangeFull> for FixedVec<T, N> {
296	fn index_mut(&mut self, index: core::ops::RangeFull) -> &mut Self::Output {
297		&mut self.0[index]
298	}
299}
300impl<T, N: Get<u32>> From<FixedVec<T, N>> for Vec<T> {
301	fn from(s: FixedVec<T, N>) -> Vec<T> {
302		s.into_vec()
303	}
304}
305impl<T, N: Get<u32>> TryFrom<Vec<T>> for FixedVec<T, N> {
306	type Error = ();
307	fn try_from(v: Vec<T>) -> Result<Self, ()> {
308		if v.len() != N::get() as usize {
309			return Err(())
310		}
311		Ok(Self(BoundedVec::truncate_from(v)))
312	}
313}
314impl<T, N: Get<u32>> From<FixedVec<T, N>> for BoundedVec<T, N> {
315	fn from(s: FixedVec<T, N>) -> BoundedVec<T, N> {
316		s.0
317	}
318}
319impl<T, N: Get<u32>> TryFrom<BoundedVec<T, N>> for FixedVec<T, N> {
320	type Error = ();
321	fn try_from(v: BoundedVec<T, N>) -> Result<Self, ()> {
322		if v.len() != N::get() as usize {
323			return Err(())
324		}
325		Ok(Self(v))
326	}
327}
328impl<'a, T: Clone, N: Get<u32>> TryFrom<&'a [T]> for FixedVec<T, N> {
329	type Error = ();
330	fn try_from(v: &'a [T]) -> Result<Self, ()> {
331		if v.len() != N::get() as usize {
332			return Err(())
333		}
334		Ok(Self(BoundedVec::truncate_from(v.to_vec())))
335	}
336}
337#[cfg(feature = "serde")]
338impl<'de, T, S: Get<u32>> serde::Deserialize<'de> for FixedVec<T, S>
339where
340	T: serde::Deserialize<'de>,
341{
342	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
343	where
344		D: serde::Deserializer<'de>,
345	{
346		use serde::de::Error;
347		let result = BoundedVec::deserialize(deserializer)?;
348		if result.len() != S::get() as usize {
349			return Err(D::Error::custom("Invalid FixedVec length"))
350		}
351		Ok(Self(result))
352	}
353}
354
355#[cfg(feature = "serde")]
356impl<T, S: Get<u32>> serde::Serialize for FixedVec<T, S>
357where
358	T: serde::Serialize,
359{
360	fn serialize<SR>(&self, serializer: SR) -> Result<SR::Ok, SR::Error>
361	where
362		SR: serde::Serializer,
363	{
364		self.0.serialize(serializer)
365	}
366}