gear_core/
buffer.rs

1// This file is part of Gear.
2
3// Copyright (C) 2021-2025 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Vector with limited len realization.
20
21use 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/// Limited len vector.
37/// `T` is data type.
38/// `E` is overflow error type.
39/// `N` is max len which a vector can have.
40#[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
44/// Formatter for [`LimitedVec`] will print to precision of 8 by default, to print the whole data, use `{:+}`.
45impl<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    /// Maximum length of the vector.
105    pub const MAX_LEN: usize = N;
106
107    /// Constructs a new, empty `LimitedVec<T>`.
108    pub const fn new() -> Self {
109        Self(Vec::new(), PhantomData)
110    }
111
112    /// Tries to create new limited vector of length `len`
113    /// with default initialized elements.
114    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    /// Creates new limited vector with default initialized elements.
120    pub fn new_default() -> Self {
121        Self(vec![T::default(); N], PhantomData)
122    }
123
124    /// Creates limited vector filled with the specified `value`.
125    pub fn filled_with(value: T) -> Self {
126        Self(vec![value; N], PhantomData)
127    }
128
129    /// Extends the array to its limit and fills with the specified `value`.
130    pub fn extend_with(&mut self, value: T) {
131        self.0.resize(N, value);
132    }
133
134    /// Append `value` to the end of vector.
135    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    /// Append `values` to the end of vector.
142    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    /// Append `values` to the begin of vector.
155    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    /// Returns ref to the internal data.
168    pub fn inner(&self) -> &[T] {
169        &self.0
170    }
171
172    /// Returns mut ref to the internal data slice.
173    pub fn inner_mut(&mut self) -> &mut [T] {
174        &mut self.0
175    }
176
177    /// Clones self into vector.
178    pub fn to_vec(&self) -> Vec<T> {
179        self.0.clone()
180    }
181
182    /// Destruct limited vector and returns inner vector.
183    pub fn into_vec(self) -> Vec<T> {
184        self.0
185    }
186
187    /// Returns max len which this type of limited vector can have.
188    pub const fn max_len() -> usize {
189        N
190    }
191}
192
193/// Max memory size, which runtime can allocate at once.
194/// Substrate allocator restrict allocations bigger then 512 wasm pages at once.
195/// See more information about:
196/// https://github.com/paritytech/substrate/blob/cc4d5cc8654d280f03a13421669ba03632e14aa7/client/allocator/src/freeing_bump.rs#L136-L149
197/// https://github.com/paritytech/substrate/blob/cc4d5cc8654d280f03a13421669ba03632e14aa7/primitives/core/src/lib.rs#L385-L388
198const RUNTIME_MAX_ALLOC_SIZE: usize = 512 * 0x10000;
199
200/// Take half from [RUNTIME_MAX_ALLOC_SIZE] in order to avoid problems with capacity overflow.
201const RUNTIME_MAX_BUFF_SIZE: usize = RUNTIME_MAX_ALLOC_SIZE / 2;
202
203/// Runtime buffer size exceed error
204#[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
221/// Wrapper for payload slice.
222pub struct PayloadSlice {
223    /// Start of the slice.
224    start: usize,
225    /// End of the slice.
226    end: usize,
227    /// Payload
228    payload: Arc<Payload>,
229}
230
231impl PayloadSlice {
232    /// Try to create a new PayloadSlice.
233    pub fn try_new(start: u32, end: u32, payload: Arc<Payload>) -> Option<Self> {
234        // Check if start and end are within the bounds of the payload
235        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    /// Get slice of the payload.
247    pub fn slice(&self) -> &[u8] {
248        &self.payload.inner()[self.start..self.end]
249    }
250}
251
252/// Buffer which size cannot be bigger then max allowed allocation size in runtime.
253pub type RuntimeBuffer = LimitedVec<u8, RuntimeBufferSizeError, RUNTIME_MAX_BUFF_SIZE>;
254
255/// Max payload size which one message can have (8 MiB).
256pub const MAX_PAYLOAD_SIZE: usize = 8 * 1024 * 1024;
257
258// **WARNING**: do not remove this check
259const _: () = assert!(MAX_PAYLOAD_SIZE <= u32::MAX as usize);
260
261/// Payload size exceed error
262#[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
280/// Payload type for message.
281pub type Payload = LimitedVec<u8, PayloadSizeError, MAX_PAYLOAD_SIZE>;
282
283impl Payload {
284    /// Get payload length as u32.
285    pub fn len_u32(&self) -> u32 {
286        // Safe, cause it's guarantied: `MAX_PAYLOAD_SIZE` <= u32::MAX
287        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/// Panic buffer which size cannot be bigger then max allowed payload size.
298#[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    /// Returns ref to the internal data.
317    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        // `Debug`/`Display`.
441        assert_eq!(
442            format!("{buffer:+?}"),
443            "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
444        );
445        // `Debug`/`Display` with default precision.
446        assert_eq!(
447            format!("{buffer:?}"),
448            "0x6162636465666768..797a303132333435"
449        );
450        // `Debug`/`Display` with precision 0.
451        assert_eq!(format!("{buffer:.0?}"), "0x..");
452        // `Debug`/`Display` with precision 1.
453        assert_eq!(format!("{buffer:.1?}"), "0x61..35");
454        // `Debug`/`Display` with precision 2.
455        assert_eq!(format!("{buffer:.2?}"), "0x6162..3435");
456        // `Debug`/`Display` with precision 4.
457        assert_eq!(format!("{buffer:.4?}"), "0x61626364..32333435");
458        // `Debug`/`Display` with precision 15.
459        assert_eq!(
460            format!("{buffer:.15?}"),
461            "0x6162636465666768696a6b6c6d6e6f..72737475767778797a303132333435"
462        );
463        // `Debug`/`Display` with precision 30.
464        assert_eq!(
465            format!("{buffer:.30?}"),
466            "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
467        );
468        // Alternate formatter with default precision.
469        assert_eq!(
470            format!("{buffer:#}"),
471            "LimitedVec(0x6162636465666768..797a303132333435)"
472        );
473        // Alternate formatter with max precision.
474        assert_eq!(
475            format!("{buffer:+#}"),
476            "LimitedVec(0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435)"
477        );
478        // Alternate formatter with precision 2.
479        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}