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 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/// Limited len vector.
38/// `T` is data type.
39/// `E` is overflow error type.
40/// `N` is max len which a vector can have.
41#[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
45/// Formatter for [`LimitedVec`] will print to precision of 8 by default, to print the whole data, use `{:+}`.
46impl<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    /// Maximum length of the vector.
112    pub const MAX_LEN: usize = N;
113
114    /// Constructs a new, empty `LimitedVec<T>`.
115    pub const fn new() -> Self {
116        Self(Vec::new(), PhantomData)
117    }
118
119    /// Tries to create new limited vector of length `len`
120    /// with default initialized elements.
121    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    /// Creates new limited vector with default initialized elements.
127    pub fn new_default() -> Self {
128        Self(vec![T::default(); N], PhantomData)
129    }
130
131    /// Creates limited vector filled with the specified `value`.
132    pub fn filled_with(value: T) -> Self {
133        Self(vec![value; N], PhantomData)
134    }
135
136    /// Extends the array to its limit and fills with the specified `value`.
137    pub fn extend_with(&mut self, value: T) {
138        self.0.resize(N, value);
139    }
140
141    /// Append `value` to the end of vector.
142    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    /// Append `values` to the end of vector.
149    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    /// Append `values` to the begin of vector.
162    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    /// Returns ref to the internal data.
175    pub fn inner(&self) -> &[T] {
176        &self.0
177    }
178
179    /// Returns mut ref to the internal data slice.
180    pub fn inner_mut(&mut self) -> &mut [T] {
181        &mut self.0
182    }
183
184    /// Clones self into vector.
185    pub fn to_vec(&self) -> Vec<T> {
186        self.0.clone()
187    }
188
189    /// Destruct limited vector and returns inner vector.
190    pub fn into_vec(self) -> Vec<T> {
191        self.0
192    }
193
194    /// Returns max len which this type of limited vector can have.
195    pub const fn max_len() -> usize {
196        N
197    }
198}
199
200/// Max memory size, which runtime can allocate at once.
201/// Substrate allocator restrict allocations bigger then 512 wasm pages at once.
202/// See more information about:
203/// https://github.com/paritytech/substrate/blob/cc4d5cc8654d280f03a13421669ba03632e14aa7/client/allocator/src/freeing_bump.rs#L136-L149
204/// https://github.com/paritytech/substrate/blob/cc4d5cc8654d280f03a13421669ba03632e14aa7/primitives/core/src/lib.rs#L385-L388
205const RUNTIME_MAX_ALLOC_SIZE: usize = 512 * 0x10000;
206
207/// Take half from [RUNTIME_MAX_ALLOC_SIZE] in order to avoid problems with capacity overflow.
208const RUNTIME_MAX_BUFF_SIZE: usize = RUNTIME_MAX_ALLOC_SIZE / 2;
209
210/// Runtime buffer size exceed error
211#[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
228/// Wrapper for payload slice.
229pub struct PayloadSlice {
230    /// Start of the slice.
231    start: usize,
232    /// End of the slice.
233    end: usize,
234    /// Payload
235    payload: Arc<Payload>,
236}
237
238impl PayloadSlice {
239    /// Try to create a new PayloadSlice.
240    pub fn try_new(start: u32, end: u32, payload: Arc<Payload>) -> Option<Self> {
241        // Check if start and end are within the bounds of the payload
242        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    /// Get slice of the payload.
254    pub fn slice(&self) -> &[u8] {
255        &self.payload.inner()[self.start..self.end]
256    }
257}
258
259/// Buffer which size cannot be bigger then max allowed allocation size in runtime.
260pub type RuntimeBuffer = LimitedVec<u8, RuntimeBufferSizeError, RUNTIME_MAX_BUFF_SIZE>;
261
262/// Max payload size which one message can have (8 MiB).
263pub const MAX_PAYLOAD_SIZE: usize = 8 * 1024 * 1024;
264
265// **WARNING**: do not remove this check
266const _: () = assert!(MAX_PAYLOAD_SIZE <= u32::MAX as usize);
267
268/// Payload size exceed error
269#[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
287/// Payload type for message.
288pub type Payload = LimitedVec<u8, PayloadSizeError, MAX_PAYLOAD_SIZE>;
289
290impl Payload {
291    /// Get payload length as u32.
292    pub fn len_u32(&self) -> u32 {
293        // Safe, cause it's guarantied: `MAX_PAYLOAD_SIZE` <= u32::MAX
294        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/// Panic buffer which size cannot be bigger then max allowed payload size.
305#[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    /// Returns ref to the internal data.
324    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        // `Debug`/`Display`.
448        assert_eq!(
449            format!("{buffer:+?}"),
450            "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
451        );
452        // `Debug`/`Display` with default precision.
453        assert_eq!(
454            format!("{buffer:?}"),
455            "0x6162636465666768..797a303132333435"
456        );
457        // `Debug`/`Display` with precision 0.
458        assert_eq!(format!("{buffer:.0?}"), "0x..");
459        // `Debug`/`Display` with precision 1.
460        assert_eq!(format!("{buffer:.1?}"), "0x61..35");
461        // `Debug`/`Display` with precision 2.
462        assert_eq!(format!("{buffer:.2?}"), "0x6162..3435");
463        // `Debug`/`Display` with precision 4.
464        assert_eq!(format!("{buffer:.4?}"), "0x61626364..32333435");
465        // `Debug`/`Display` with precision 15.
466        assert_eq!(
467            format!("{buffer:.15?}"),
468            "0x6162636465666768696a6b6c6d6e6f..72737475767778797a303132333435"
469        );
470        // `Debug`/`Display` with precision 30.
471        assert_eq!(
472            format!("{buffer:.30?}"),
473            "0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435"
474        );
475        // Alternate formatter with default precision.
476        assert_eq!(
477            format!("{buffer:#}"),
478            "LimitedVec(0x6162636465666768..797a303132333435)"
479        );
480        // Alternate formatter with max precision.
481        assert_eq!(
482            format!("{buffer:+#}"),
483            "LimitedVec(0x6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435)"
484        );
485        // Alternate formatter with precision 2.
486        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}