1
+ use crate :: conversion:: to_u32;
2
+ use crate :: errors:: StdResult ;
3
+
1
4
/// A sections decoder for the special case of two elements
2
5
#[ allow( dead_code) ] // used in Wasm and tests only
3
6
pub fn decode_sections2 ( data : Vec < u8 > ) -> ( Vec < u8 > , Vec < u8 > ) {
@@ -6,6 +9,33 @@ pub fn decode_sections2(data: Vec<u8>) -> (Vec<u8>, Vec<u8>) {
6
9
( first, second)
7
10
}
8
11
12
+ /// Encodes multiple sections of data into one vector.
13
+ ///
14
+ /// Each section is suffixed by a section length encoded as big endian uint32.
15
+ /// Using suffixes instead of prefixes allows reading sections in reverse order,
16
+ /// such that the first element does not need to be re-allocated if the contract's
17
+ /// data structure supports truncation (such as a Rust vector).
18
+ ///
19
+ /// The resulting data looks like this:
20
+ ///
21
+ /// ```ignore
22
+ /// section1 || section1_len || section2 || section2_len || section3 || section3_len || …
23
+ /// ```
24
+ #[ allow( dead_code) ] // used in Wasm and tests only
25
+ pub fn encode_sections ( sections : & [ Vec < u8 > ] ) -> StdResult < Vec < u8 > > {
26
+ let mut out_len: usize = sections. iter ( ) . map ( |section| section. len ( ) ) . sum ( ) ;
27
+ out_len += 4 * sections. len ( ) ;
28
+ let mut out_data = Vec :: with_capacity ( out_len) ;
29
+ for section in sections {
30
+ let section_len = to_u32 ( section. len ( ) ) ?. to_be_bytes ( ) ;
31
+ out_data. extend ( section) ;
32
+ out_data. extend_from_slice ( & section_len) ;
33
+ }
34
+ debug_assert_eq ! ( out_data. len( ) , out_len) ;
35
+ debug_assert_eq ! ( out_data. capacity( ) , out_len) ;
36
+ Ok ( out_data)
37
+ }
38
+
9
39
/// Splits data into the last section ("tail") and the rest.
10
40
/// The tail's length information is cut off, such that it is ready to use.
11
41
/// The rest is basically unparsed and contails the lengths of the remaining sections.
@@ -76,4 +106,40 @@ mod tests {
76
106
assert_ne ! ( second. capacity( ) , original_capacity) ;
77
107
assert_ne ! ( second. as_ptr( ) , original_ptr) ;
78
108
}
109
+
110
+ #[ test]
111
+ fn encode_sections_works_for_empty_sections ( ) {
112
+ let enc = encode_sections ( & [ ] ) . unwrap ( ) ;
113
+ assert_eq ! ( enc, b"" as & [ u8 ] ) ;
114
+ let enc = encode_sections ( & [ vec ! [ ] ] ) . unwrap ( ) ;
115
+ assert_eq ! ( enc, b"\0 \0 \0 \0 " as & [ u8 ] ) ;
116
+ let enc = encode_sections ( & [ vec ! [ ] , vec ! [ ] ] ) . unwrap ( ) ;
117
+ assert_eq ! ( enc, b"\0 \0 \0 \0 \0 \0 \0 \0 " as & [ u8 ] ) ;
118
+ let enc = encode_sections ( & [ vec ! [ ] , vec ! [ ] , vec ! [ ] ] ) . unwrap ( ) ;
119
+ assert_eq ! ( enc, b"\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 " as & [ u8 ] ) ;
120
+ }
121
+
122
+ #[ test]
123
+ fn encode_sections_works_for_one_element ( ) {
124
+ let enc = encode_sections ( & [ ] ) . unwrap ( ) ;
125
+ assert_eq ! ( enc, b"" as & [ u8 ] ) ;
126
+ let enc = encode_sections ( & [ vec ! [ 0xAA ] ] ) . unwrap ( ) ;
127
+ assert_eq ! ( enc, b"\xAA \0 \0 \0 \x01 " as & [ u8 ] ) ;
128
+ let enc = encode_sections ( & [ vec ! [ 0xAA , 0xBB ] ] ) . unwrap ( ) ;
129
+ assert_eq ! ( enc, b"\xAA \xBB \0 \0 \0 \x02 " as & [ u8 ] ) ;
130
+ let enc = encode_sections ( & [ vec ! [ 0x9D ; 277 ] ] ) . unwrap ( ) ;
131
+ assert_eq ! ( enc, 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 " as & [ u8 ] ) ;
132
+ }
133
+
134
+ #[ test]
135
+ fn encode_sections_works_for_multiple_elements ( ) {
136
+ let enc = encode_sections ( & [ vec ! [ 0xAA ] ] ) . unwrap ( ) ;
137
+ assert_eq ! ( enc, b"\xAA \0 \0 \0 \x01 " as & [ u8 ] ) ;
138
+ let enc = encode_sections ( & [ vec ! [ 0xAA ] , vec ! [ 0xDE , 0xDE ] ] ) . unwrap ( ) ;
139
+ assert_eq ! ( enc, b"\xAA \0 \0 \0 \x01 \xDE \xDE \0 \0 \0 \x02 " as & [ u8 ] ) ;
140
+ let enc = encode_sections ( & [ vec ! [ 0xAA ] , vec ! [ 0xDE , 0xDE ] , vec ! [ ] ] ) . unwrap ( ) ;
141
+ assert_eq ! ( enc, b"\xAA \0 \0 \0 \x01 \xDE \xDE \0 \0 \0 \x02 \0 \0 \0 \0 " as & [ u8 ] ) ;
142
+ let enc = encode_sections ( & [ vec ! [ 0xAA ] , vec ! [ 0xDE , 0xDE ] , vec ! [ ] , vec ! [ 0xFF ; 19 ] ] ) . unwrap ( ) ;
143
+ 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 ] ) ;
144
+ }
79
145
}
0 commit comments