substrate_parser/
compacts.rs1use external_memory_tools::{AddressableBuffer, BufferError, ExternalMemory};
3use parity_scale_codec::{Compact, Decode, HasCompact};
4
5use crate::error::ParserError;
6
7#[derive(Debug)]
9pub struct FoundCompact<T: HasCompact> {
10 pub compact: T,
12
13 pub start_next_unit: usize,
15}
16
17pub const MAX_COMPACT_LEN: usize = 17;
21
22pub fn find_compact<T, B, E>(
27 data: &B,
28 ext_memory: &mut E,
29 position: usize,
30) -> Result<FoundCompact<T>, ParserError<E>>
31where
32 B: AddressableBuffer<E>,
33 E: ExternalMemory,
34 T: HasCompact,
35 Compact<T>: Decode,
36{
37 if data.total_len() < position {
38 return Err(ParserError::Buffer(BufferError::OutOfRange {
39 position,
40 total_length: data.total_len(),
41 }));
42 }
43 let mut out = None;
44 for i in 0..(data.total_len() - position) {
45 if i > MAX_COMPACT_LEN {
47 break;
48 }
49
50 let hippo = data.read_slice(ext_memory, position, i + 1)?;
51 let unhippo = <Compact<T>>::decode(&mut hippo.as_ref());
52 if let Ok(hurray) = unhippo {
53 let start_next_unit = {
54 if data.total_len() - position == i {
55 data.total_len()
56 } else {
57 position + i + 1
58 }
59 };
60 out = Some(FoundCompact {
61 compact: hurray.0,
62 start_next_unit,
63 });
64 break;
65 }
66 }
67 match out {
68 Some(c) => Ok(c),
69 None => Err(ParserError::NoCompact { position }),
70 }
71}
72
73pub fn get_compact<T, B, E>(
75 data: &B,
76 ext_memory: &mut E,
77 position: &mut usize,
78) -> Result<T, ParserError<E>>
79where
80 B: AddressableBuffer<E>,
81 E: ExternalMemory,
82 T: HasCompact,
83 Compact<T>: Decode,
84{
85 let found_compact = find_compact::<T, B, E>(data, ext_memory, *position)?;
86 *position = found_compact.start_next_unit;
87 Ok(found_compact.compact)
88}