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