1use core::{
22 convert::TryFrom,
23 fmt::{self, Debug, Display, Formatter},
24 marker::PhantomData,
25};
26
27use alloc::{sync::Arc, vec, vec::Vec};
28use core::hash::{Hash, Hasher};
29use parity_scale_codec::{Compact, MaxEncodedLen};
30use scale_info::{
31 TypeInfo,
32 scale::{Decode, Encode},
33};
34
35use crate::str::LimitedStr;
36
37#[derive(Clone, Default, Eq, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo)]
42#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
43pub struct LimitedVec<T, E, const N: usize>(Vec<T>, PhantomData<E>);
44
45impl<T: Clone + Default, E: Default, const N: usize> Display for LimitedVec<T, E, N>
47where
48 [T]: AsRef<[u8]>,
49{
50 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
51 let len = self.0.len();
52 let median = len.div_ceil(2);
53
54 let mut e1 = median;
55 let mut s2 = median;
56
57 if let Some(precision) = f.precision() {
58 if precision < median {
59 e1 = precision;
60 s2 = len - precision;
61 }
62 } else if !f.sign_plus() && median > 8 {
63 e1 = 8;
64 s2 = len - 8;
65 }
66
67 let p1 = hex::encode(&self.0[..e1]);
68 let p2 = hex::encode(&self.0[s2..]);
69 let sep = if e1.ne(&s2) { ".." } else { Default::default() };
70
71 if f.alternate() {
72 write!(f, "LimitedVec(0x{p1}{sep}{p2})")
73 } else {
74 write!(f, "0x{p1}{sep}{p2}")
75 }
76 }
77}
78
79impl<T: Clone + Default, E: Default, const N: usize> Debug for LimitedVec<T, E, N>
80where
81 [T]: AsRef<[u8]>,
82{
83 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84 core::fmt::Display::fmt(self, f)
85 }
86}
87
88impl<T: Clone, E: Default, const N: usize> TryFrom<&[T]> for LimitedVec<T, E, N> {
89 type Error = E;
90 fn try_from(x: &[T]) -> Result<Self, Self::Error> {
91 (x.len() <= N).then_some(()).ok_or_else(E::default)?;
92 Ok(Self(Vec::from(x), PhantomData))
93 }
94}
95
96impl<T, E: Default, const N: usize> TryFrom<Vec<T>> for LimitedVec<T, E, N> {
97 type Error = E;
98 fn try_from(x: Vec<T>) -> Result<Self, Self::Error> {
99 (x.len() <= N).then_some(()).ok_or_else(E::default)?;
100 Ok(Self(x, PhantomData))
101 }
102}
103
104impl<T: Hash, E: Default, const N: usize> Hash for LimitedVec<T, E, N> {
105 fn hash<H: Hasher>(&self, state: &mut H) {
106 self.0.hash(state);
107 }
108}
109
110impl<T: Clone + Default, E: Default, const N: usize> LimitedVec<T, E, N> {
111 pub const MAX_LEN: usize = N;
113
114 pub const fn new() -> Self {
116 Self(Vec::new(), PhantomData)
117 }
118
119 pub fn try_new_default(len: usize) -> Result<Self, E> {
122 (len <= N).then_some(()).ok_or_else(E::default)?;
123 Ok(Self(vec![T::default(); len], PhantomData))
124 }
125
126 pub fn new_default() -> Self {
128 Self(vec![T::default(); N], PhantomData)
129 }
130
131 pub fn filled_with(value: T) -> Self {
133 Self(vec![value; N], PhantomData)
134 }
135
136 pub fn extend_with(&mut self, value: T) {
138 self.0.resize(N, value);
139 }
140
141 pub fn try_push(&mut self, value: T) -> Result<(), E> {
143 (self.0.len() != N).then_some(()).ok_or_else(E::default)?;
144 self.0.push(value);
145 Ok(())
146 }
147
148 pub fn try_extend_from_slice(&mut self, values: &[T]) -> Result<(), E> {
150 self.0
151 .len()
152 .checked_add(values.len())
153 .and_then(|len| (len <= N).then_some(()))
154 .ok_or_else(E::default)?;
155
156 self.0.extend_from_slice(values);
157
158 Ok(())
159 }
160
161 pub fn try_prepend(&mut self, values: Self) -> Result<(), E> {
163 self.0
164 .len()
165 .checked_add(values.0.len())
166 .and_then(|len| (len <= N).then_some(()))
167 .ok_or_else(E::default)?;
168
169 self.0.splice(0..0, values.0);
170
171 Ok(())
172 }
173
174 pub fn inner(&self) -> &[T] {
176 &self.0
177 }
178
179 pub fn inner_mut(&mut self) -> &mut [T] {
181 &mut self.0
182 }
183
184 pub fn to_vec(&self) -> Vec<T> {
186 self.0.clone()
187 }
188
189 pub fn into_vec(self) -> Vec<T> {
191 self.0
192 }
193
194 pub const fn max_len() -> usize {
196 N
197 }
198}
199
200const RUNTIME_MAX_ALLOC_SIZE: usize = 512 * 0x10000;
206
207const RUNTIME_MAX_BUFF_SIZE: usize = RUNTIME_MAX_ALLOC_SIZE / 2;
209
210#[derive(
212 Clone, Copy, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
213)]
214pub struct RuntimeBufferSizeError;
215
216impl From<RuntimeBufferSizeError> for &str {
217 fn from(_: RuntimeBufferSizeError) -> Self {
218 "Runtime buffer size exceed"
219 }
220}
221
222impl Display for RuntimeBufferSizeError {
223 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
224 f.write_str((*self).into())
225 }
226}
227
228pub struct PayloadSlice {
230 start: usize,
232 end: usize,
234 payload: Arc<Payload>,
236}
237
238impl PayloadSlice {
239 pub fn try_new(start: u32, end: u32, payload: Arc<Payload>) -> Option<Self> {
241 if start > end || end > payload.len_u32() {
243 return None;
244 }
245
246 Some(Self {
247 start: start as usize,
248 end: end as usize,
249 payload,
250 })
251 }
252
253 pub fn slice(&self) -> &[u8] {
255 &self.payload.inner()[self.start..self.end]
256 }
257}
258
259pub type RuntimeBuffer = LimitedVec<u8, RuntimeBufferSizeError, RUNTIME_MAX_BUFF_SIZE>;
261
262pub const MAX_PAYLOAD_SIZE: usize = 8 * 1024 * 1024;
264
265const _: () = assert!(MAX_PAYLOAD_SIZE <= u32::MAX as usize);
267
268#[derive(
270 Clone, Copy, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo,
271)]
272#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
273pub struct PayloadSizeError;
274
275impl From<PayloadSizeError> for &str {
276 fn from(_: PayloadSizeError) -> Self {
277 "Payload size limit exceeded"
278 }
279}
280
281impl Display for PayloadSizeError {
282 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
283 f.write_str((*self).into())
284 }
285}
286
287pub type Payload = LimitedVec<u8, PayloadSizeError, MAX_PAYLOAD_SIZE>;
289
290impl Payload {
291 pub fn len_u32(&self) -> u32 {
293 self.inner().len() as u32
295 }
296}
297
298impl MaxEncodedLen for Payload {
299 fn max_encoded_len() -> usize {
300 Compact::<u32>::max_encoded_len() + MAX_PAYLOAD_SIZE
301 }
302}
303
304#[derive(
306 Clone,
307 Default,
308 Eq,
309 Hash,
310 Ord,
311 PartialEq,
312 PartialOrd,
313 Decode,
314 Encode,
315 TypeInfo,
316 derive_more::From,
317 derive_more::Into,
318)]
319#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
320pub struct PanicBuffer(Payload);
321
322impl PanicBuffer {
323 pub fn inner(&self) -> &Payload {
325 &self.0
326 }
327
328 fn to_limited_str(&self) -> Option<LimitedStr<'_>> {
329 let s = core::str::from_utf8(self.0.inner()).ok()?;
330 LimitedStr::try_from(s).ok()
331 }
332}
333
334impl From<LimitedStr<'_>> for PanicBuffer {
335 fn from(value: LimitedStr) -> Self {
336 const _: () = assert!(crate::str::TRIMMED_MAX_LEN <= MAX_PAYLOAD_SIZE);
337 Payload::try_from(value.into_inner().into_owned().into_bytes())
338 .map(Self)
339 .unwrap_or_else(|PayloadSizeError| {
340 unreachable!("`LimitedStr` is always smaller than maximum payload size",)
341 })
342 }
343}
344
345impl Display for PanicBuffer {
346 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
347 if let Some(s) = self.to_limited_str() {
348 Display::fmt(&s, f)
349 } else {
350 Display::fmt(&self.0, f)
351 }
352 }
353}
354
355impl Debug for PanicBuffer {
356 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
357 if let Some(s) = self.to_limited_str() {
358 Debug::fmt(s.as_str(), f)
359 } else {
360 Debug::fmt(&self.0, f)
361 }
362 }
363}
364
365#[cfg(test)]
366mod test {
367 use super::{LimitedVec, PanicBuffer, Payload, RuntimeBufferSizeError};
368 use alloc::{format, string::String, vec, vec::Vec};
369 use core::convert::{TryFrom, TryInto};
370
371 const N: usize = 1000;
372 type TestBuffer = LimitedVec<u8, RuntimeBufferSizeError, N>;
373 const M: usize = 64;
374 type SmallTestBuffer = LimitedVec<u8, RuntimeBufferSizeError, M>;
375
376 #[test]
377 fn test_try_from() {
378 let v1 = vec![1; N];
379 let v2 = vec![1; N + 1];
380 let v3 = vec![1; N - 1];
381
382 let x = TestBuffer::try_from(v1).unwrap();
383 let _ = TestBuffer::try_from(v2).expect_err("Must be err because of size overflow");
384 let z = TestBuffer::try_from(v3).unwrap();
385
386 assert_eq!(x.inner().len(), N);
387 assert_eq!(z.inner().len(), N - 1);
388 assert_eq!(x.inner()[N / 2], 1);
389 assert_eq!(z.inner()[N / 2], 1);
390 }
391
392 #[test]
393 fn test_new_default() {
394 let x = LimitedVec::<String, RuntimeBufferSizeError, N>::try_new_default(N).unwrap();
395 assert!(
396 LimitedVec::<u64, RuntimeBufferSizeError, N>::try_new_default(N + 1).is_err(),
397 "Must be error because of size overflow"
398 );
399 let z = LimitedVec::<Vec<u8>, RuntimeBufferSizeError, N>::try_new_default(0).unwrap();
400
401 assert_eq!(x.inner().len(), N);
402 assert_eq!(z.inner().len(), 0);
403 assert_eq!(x.inner()[N / 2], "");
404 }
405
406 #[test]
407 fn test_prepend_works() {
408 let mut buf = TestBuffer::try_from(vec![1, 2, 3, 4, 5]).unwrap();
409 let prepend_buf = TestBuffer::try_from(vec![6, 7, 8]).unwrap();
410 buf.try_prepend(prepend_buf).unwrap();
411
412 assert_eq!(buf.inner(), &[6, 7, 8, 1, 2, 3, 4, 5]);
413 }
414
415 #[test]
416 fn test_full() {
417 let mut x = TestBuffer::try_from(vec![1; N]).unwrap();
418 let mut y = TestBuffer::try_from(vec![2; N / 2]).unwrap();
419 let mut z = TestBuffer::try_from(vec![3; 0]).unwrap();
420
421 x.try_push(42).unwrap_err();
422 y.try_push(42).unwrap();
423 z.try_push(42).unwrap();
424
425 x.try_extend_from_slice(&[1, 2, 3]).unwrap_err();
426 y.try_extend_from_slice(&[1, 2, 3]).unwrap();
427 z.try_extend_from_slice(&[1, 2, 3]).unwrap();
428
429 x.try_prepend(vec![1, 2, 3].try_into().unwrap())
430 .unwrap_err();
431 y.try_prepend(vec![1, 2, 3].try_into().unwrap()).unwrap();
432 z.try_prepend(vec![1, 2, 3].try_into().unwrap()).unwrap();
433
434 z.inner_mut()[0] = 0;
435
436 assert_eq!(&z.into_vec(), &[0, 2, 3, 42, 1, 2, 3]);
437 assert_eq!(TestBuffer::max_len(), N);
438 }
439
440 #[test]
441 fn formatting_test() {
442 use alloc::format;
443
444 let buffer = SmallTestBuffer::try_from(b"abcdefghijklmnopqrstuvwxyz012345".to_vec())
445 .expect("String is 64 bytes");
446
447 assert_eq!(
449 format!("{buffer:+?}"),
450 "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
451 );
452 assert_eq!(
454 format!("{buffer:?}"),
455 "0x6162636465666768..797a303132333435"
456 );
457 assert_eq!(format!("{buffer:.0?}"), "0x..");
459 assert_eq!(format!("{buffer:.1?}"), "0x61..35");
461 assert_eq!(format!("{buffer:.2?}"), "0x6162..3435");
463 assert_eq!(format!("{buffer:.4?}"), "0x61626364..32333435");
465 assert_eq!(
467 format!("{buffer:.15?}"),
468 "0x6162636465666768696a6b6c6d6e6f..72737475767778797a303132333435"
469 );
470 assert_eq!(
472 format!("{buffer:.30?}"),
473 "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
474 );
475 assert_eq!(
477 format!("{buffer:#}"),
478 "LimitedVec(0x6162636465666768..797a303132333435)"
479 );
480 assert_eq!(
482 format!("{buffer:+#}"),
483 "LimitedVec(0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435)"
484 );
485 assert_eq!(format!("{buffer:#.2}"), "LimitedVec(0x6162..3435)");
487 }
488
489 fn panic_buf(bytes: &[u8]) -> PanicBuffer {
490 Payload::try_from(bytes).map(PanicBuffer).unwrap()
491 }
492
493 #[test]
494 fn panic_buffer_debug() {
495 let buf = panic_buf(b"Hello, world!");
496 assert_eq!(format!("{buf:?}"), r#""Hello, world!""#);
497
498 let buf = panic_buf(b"\xE0\x80\x80");
499 assert_eq!(format!("{buf:?}"), "0xe08080");
500 }
501
502 #[test]
503 fn panic_buffer_display() {
504 let buf = panic_buf(b"Hello, world!");
505 assert_eq!(format!("{buf}"), "Hello, world!");
506
507 let buf = panic_buf(b"\xE0\x80\x80");
508 assert_eq!(format!("{buf}"), "0xe08080");
509 }
510}