1use core::fmt::{self, Formatter};
22
23use alloc::{vec, vec::Vec};
24
25use derive_more::{AsMut, AsRef, Debug, Deref, DerefMut, Display, Error, Into, IntoIterator};
26use gprimitives::utils::ByteSliceFormatter;
27use scale_decode::DecodeAsType;
28use scale_encode::EncodeAsType;
29use scale_info::{
30 TypeInfo,
31 scale::{Decode, Encode},
32};
33
34#[derive(
36 Clone,
37 Default,
38 PartialEq,
39 Eq,
40 PartialOrd,
41 Ord,
42 Decode,
43 DecodeAsType,
44 Encode,
45 EncodeAsType,
46 Hash,
47 TypeInfo,
48 AsRef,
49 AsMut,
50 Deref,
51 DerefMut,
52 IntoIterator,
53 Into,
54)]
55#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
56#[as_ref(forward)]
57#[as_mut(forward)]
58#[deref(forward)]
59#[deref_mut(forward)]
60#[into_iterator(owned, ref, ref_mut)]
61pub struct LimitedVec<T, const N: usize>(Vec<T>);
62
63impl<T: Clone, const N: usize> TryFrom<&[T]> for LimitedVec<T, N> {
64 type Error = LimitedVecError;
65
66 fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
67 Self::validate_len(slice.len()).map(|_| Self(slice.to_vec()))
68 }
69}
70
71impl<T, const N: usize> TryFrom<Vec<T>> for LimitedVec<T, N> {
72 type Error = LimitedVecError;
73 fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
74 Self::validate_len(vec.len()).map(|_| Self(vec))
75 }
76}
77
78impl<T, const N: usize> LimitedVec<T, N> {
79 pub const MAX_LEN: usize = N;
81
82 const fn validate_len(len: usize) -> Result<(), LimitedVecError> {
87 if len <= N {
88 Ok(())
89 } else {
90 Err(LimitedVecError)
91 }
92 }
93
94 pub const fn new() -> Self {
96 Self(vec![])
97 }
98
99 pub fn repeat(value: T) -> Self
102 where
103 T: Clone,
104 {
105 Self(vec![value; N])
106 }
107
108 pub fn try_repeat(value: T, len: usize) -> Result<Self, LimitedVecError>
111 where
112 T: Clone,
113 {
114 Self::validate_len(len).map(|_| Self(vec![value; len]))
115 }
116
117 pub fn extend_with(&mut self, value: T)
120 where
121 T: Clone,
122 {
123 self.0.resize(N, value)
124 }
125
126 pub fn try_push(&mut self, value: T) -> Result<(), LimitedVecError> {
128 Self::validate_len(self.len() + 1)?;
129
130 self.0.push(value);
131 Ok(())
132 }
133
134 pub fn try_extend_from_slice(&mut self, values: &[T]) -> Result<(), LimitedVecError>
136 where
137 T: Clone,
138 {
139 let new_len = self
140 .len()
141 .checked_add(values.len())
142 .ok_or(LimitedVecError)?;
143 Self::validate_len(new_len)?;
144
145 self.0.extend_from_slice(values);
146 Ok(())
147 }
148
149 pub fn as_slice(&self) -> &[T] {
151 self
152 }
153
154 pub fn to_vec(&self) -> Vec<T>
156 where
157 T: Clone,
158 {
159 self.0.clone()
160 }
161
162 pub fn into_vec(self) -> Vec<T> {
164 self.0
165 }
166}
167
168impl<T, const N: usize> fmt::Display for LimitedVec<T, N>
169where
170 [T]: AsRef<[u8]>,
171{
172 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
173 let bytes = ByteSliceFormatter::Dynamic(self.0.as_slice().as_ref());
174
175 let fmt_bytes = |f: &mut Formatter, bytes| {
185 if f.alternate() {
186 write!(f, "LimitedVec({bytes})")
187 } else {
188 write!(f, "{bytes}")
189 }
190 };
191
192 if let Some(precision) = f.precision() {
193 fmt_bytes(f, format_args!("{bytes:.precision$}"))
194 } else if f.sign_plus() {
195 fmt_bytes(f, format_args!("{bytes}"))
196 } else {
197 fmt_bytes(f, format_args!("{bytes:.8}"))
198 }
199 }
200}
201
202impl<T, const N: usize> fmt::Debug for LimitedVec<T, N>
203where
204 [T]: AsRef<[u8]>,
205{
206 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
207 fmt::Display::fmt(self, f)
208 }
209}
210
211#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Display, Error)]
213#[display("{}", Self::MESSAGE)]
214pub struct LimitedVecError;
215
216impl LimitedVecError {
217 pub const MESSAGE: &str = "vector length limit is exceeded";
219
220 pub const fn as_str(&self) -> &'static str {
222 Self::MESSAGE
223 }
224}
225
226#[cfg(test)]
227mod test {
228 use super::LimitedVec;
229 use alloc::{string::String, vec, vec::Vec};
230 use core::convert::TryFrom;
231
232 const N: usize = 1000;
233 type TestBuffer = LimitedVec<u8, N>;
234 const M: usize = 64;
235 type SmallTestBuffer = LimitedVec<u8, M>;
236
237 #[test]
238 fn test_try_from() {
239 let v1 = vec![1; N];
240 let v2 = vec![1; N + 1];
241 let v3 = vec![1; N - 1];
242
243 let x = TestBuffer::try_from(v1).unwrap();
244 let _ = TestBuffer::try_from(v2).expect_err("Must be err because of size overflow");
245 let z = TestBuffer::try_from(v3).unwrap();
246
247 assert_eq!(x.len(), N);
248 assert_eq!(z.len(), N - 1);
249 assert_eq!(x[N / 2], 1);
250 assert_eq!(z[N / 2], 1);
251 }
252
253 #[test]
254 fn test_repeat() {
255 let x = LimitedVec::<u32, N>::repeat(0);
256 assert_eq!(x.len(), N);
257
258 let y = LimitedVec::<i32, 3>::repeat(-4);
259 assert_eq!(y.as_slice(), &[-4, -4, -4]);
260 }
261
262 #[test]
263 fn test_try_repeat() {
264 let x = LimitedVec::<String, N>::try_repeat(String::new(), N).unwrap();
265 assert!(
266 LimitedVec::<u64, N>::try_repeat(0, N + 1).is_err(),
267 "Must be error because of size overflow"
268 );
269 let y = LimitedVec::<char, 7>::try_repeat('@', 5).unwrap();
270 let z = LimitedVec::<Vec<u8>, N>::try_repeat(vec![], 0).unwrap();
271
272 assert_eq!(x.len(), N);
273 assert_eq!(z.len(), 0);
274 assert_eq!(x[N / 2], "");
275 assert_eq!(y.as_slice(), &['@', '@', '@', '@', '@']);
276 }
277
278 #[test]
279 fn test_full() {
280 let mut x = TestBuffer::try_from(vec![1; N]).unwrap();
281 let mut y = TestBuffer::try_from(vec![2; N / 2]).unwrap();
282 let mut z = TestBuffer::try_from(vec![3; 0]).unwrap();
283
284 x.try_extend_from_slice(&[1, 2, 3]).unwrap_err();
285 y.try_extend_from_slice(&[1, 2, 3]).unwrap();
286 z.try_extend_from_slice(&[1, 2, 3]).unwrap();
287
288 x.try_push(42).unwrap_err();
289 y.try_push(42).unwrap();
290 z.try_push(42).unwrap();
291
292 x.try_extend_from_slice(&[1, 2, 3]).unwrap_err();
293 y.try_extend_from_slice(&[1, 2, 3]).unwrap();
294 z.try_extend_from_slice(&[1, 2, 3]).unwrap();
295
296 z[0] = 0;
297
298 assert_eq!(&z.into_vec(), &[0, 2, 3, 42, 1, 2, 3]);
299 assert_eq!(TestBuffer::MAX_LEN, N);
300 }
301
302 #[test]
303 fn formatting_test() {
304 use alloc::format;
305
306 let buffer = SmallTestBuffer::try_from(b"abcdefghijklmnopqrstuvwxyz012345".to_vec())
307 .expect("String is 64 bytes");
308
309 assert_eq!(
311 format!("{buffer:+?}"),
312 "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
313 );
314 assert_eq!(
316 format!("{buffer:?}"),
317 "0x6162636465666768..797a303132333435"
318 );
319 assert_eq!(format!("{buffer:.0?}"), "0x..");
321 assert_eq!(format!("{buffer:.1?}"), "0x61..35");
323 assert_eq!(format!("{buffer:.2?}"), "0x6162..3435");
325 assert_eq!(format!("{buffer:.4?}"), "0x61626364..32333435");
327 assert_eq!(
329 format!("{buffer:.15?}"),
330 "0x6162636465666768696a6b6c6d6e6f..72737475767778797a303132333435"
331 );
332 assert_eq!(
334 format!("{buffer:.30?}"),
335 "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
336 );
337 assert_eq!(
339 format!("{buffer:#}"),
340 "LimitedVec(0x6162636465666768..797a303132333435)"
341 );
342 assert_eq!(
344 format!("{buffer:+#}"),
345 "LimitedVec(0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435)"
346 );
347 assert_eq!(format!("{buffer:#.2}"), "LimitedVec(0x6162..3435)");
349 }
350}