Skip to content

Commit 7bd5a9e

Browse files
committed
Add decode_sections()
1 parent 8395f54 commit 7bd5a9e

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

packages/vm/src/sections.rs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
use crate::conversion::to_u32;
22
use crate::errors::VmResult;
33

4+
/// Decodes sections of data into multiple slices.
5+
///
6+
/// Each encoded section is suffixed by a section length, encoded as big endian uint32.
7+
///
8+
/// See also: `encode_section`.
9+
pub fn decode_sections(data: &[u8]) -> Vec<&[u8]> {
10+
let mut result: Vec<&[u8]> = vec![];
11+
let lengths = extract_lengths(data);
12+
let mut start = 0;
13+
for length in lengths.iter().rev() {
14+
result.push(&data[start..start + length]);
15+
start += length + 4;
16+
}
17+
result
18+
}
19+
420
/// Encodes multiple sections of data into one vector.
521
///
622
/// Each section is suffixed by a section length encoded as big endian uint32.
@@ -28,10 +44,80 @@ pub fn encode_sections(sections: &[Vec<u8>]) -> VmResult<Vec<u8>> {
2844
Ok(out_data)
2945
}
3046

47+
/// Extracts the lengths of encoded vectors.
48+
///
49+
/// Starts from the end of `data`, and computes a (reverse) list of lengths.
50+
fn extract_lengths(data: &[u8]) -> Vec<usize> {
51+
let mut lengths = vec![];
52+
let mut remaining_len = data.len();
53+
while remaining_len >= 4 {
54+
let tail_len = u32::from_be_bytes([
55+
data[remaining_len - 4],
56+
data[remaining_len - 3],
57+
data[remaining_len - 2],
58+
data[remaining_len - 1],
59+
]) as usize;
60+
lengths.push(tail_len);
61+
remaining_len -= 4 + tail_len;
62+
}
63+
lengths
64+
}
65+
3166
#[cfg(test)]
3267
mod tests {
3368
use super::*;
3469

70+
#[test]
71+
fn decode_sections_works_for_empty_sections() {
72+
let dec = decode_sections(&[]);
73+
assert_eq!(dec.len(), 0);
74+
let dec = decode_sections(b"\0\0\0\0");
75+
assert_eq!(dec, &[&[0u8; 0]]);
76+
let dec = decode_sections(b"\0\0\0\0\0\0\0\0");
77+
assert_eq!(dec, &[&[0u8; 0]; 2]);
78+
let dec = decode_sections(b"\0\0\0\0\0\0\0\0\0\0\0\0");
79+
assert_eq!(dec, &[&[0u8; 0]; 3]);
80+
// ignores "trailing" stuff
81+
let dec = decode_sections(b"\0\0\0\0\0\0\0\0\0\0\0");
82+
assert_eq!(dec, &[&[0u8; 0]; 2]);
83+
}
84+
85+
#[test]
86+
fn decode_sections_works_for_one_element() {
87+
let dec = decode_sections(b"\xAA\0\0\0\x01");
88+
assert_eq!(dec, &[vec![0xAA]]);
89+
let dec = decode_sections(b"\xAA\xBB\0\0\0\x02");
90+
assert_eq!(dec, &[vec![0xAA, 0xBB]]);
91+
let dec = decode_sections(b"\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15");
92+
assert_eq!(dec, &[vec![0x9D; 277]]);
93+
}
94+
95+
#[test]
96+
fn decode_sections_works_for_two_elements() {
97+
let data = b"\xAA\0\0\0\x01\xBB\xCC\0\0\0\x02".to_vec();
98+
assert_eq!(decode_sections(&data), &[vec![0xAA], vec![0xBB, 0xCC]]);
99+
let data = b"\xDE\xEF\x62\0\0\0\x03\0\0\0\0".to_vec();
100+
assert_eq!(decode_sections(&data), &[vec![0xDE, 0xEF, 0x62], vec![]]);
101+
let data = b"\0\0\0\0\xDE\xEF\x62\0\0\0\x03".to_vec();
102+
assert_eq!(decode_sections(&data), &[vec![], vec![0xDE, 0xEF, 0x62]]);
103+
let data = b"\0\0\0\0\0\0\0\0".to_vec();
104+
assert_eq!(decode_sections(&data), &[vec![0u8; 0], vec![]]);
105+
let data = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15".to_vec();
106+
assert_eq!(decode_sections(&data), &[vec![0xFF; 19], vec![0x9D; 277]]);
107+
}
108+
109+
#[test]
110+
fn decode_sections_works_for_multiple_elements() {
111+
let dec = decode_sections(b"\xAA\0\0\0\x01");
112+
assert_eq!(dec, &[vec![0xAA]]);
113+
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02");
114+
assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE]]);
115+
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0");
116+
assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE], vec![]]);
117+
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13");
118+
assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]);
119+
}
120+
35121
#[test]
36122
fn encode_sections_works_for_empty_sections() {
37123
let enc = encode_sections(&[]).unwrap();
@@ -67,4 +153,4 @@ mod tests {
67153
let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]).unwrap();
68154
assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13" as &[u8]);
69155
}
70-
}
156+
}

0 commit comments

Comments
 (0)