1use crate::conversion::to_u32;
2use crate::{CommunicationError, VmResult};
3
4pub fn decode_sections(data: &[u8]) -> Result<Vec<&[u8]>, CommunicationError> {
10 let mut result: Vec<&[u8]> = vec![];
11 let mut remaining_len = data.len();
12 while remaining_len >= 4 {
13 let tail_len = u32::from_be_bytes([
14 data[remaining_len - 4],
15 data[remaining_len - 3],
16 data[remaining_len - 2],
17 data[remaining_len - 1],
18 ]) as usize;
19 let tail_len_idx = remaining_len - 4; let section_start = tail_len_idx
21 .checked_sub(tail_len)
22 .ok_or_else(|| CommunicationError::invalid_section("section length overflow"))?;
23 result.push(&data[section_start..tail_len_idx]);
24 remaining_len = section_start;
25 }
26 if remaining_len > 0 {
27 return Err(CommunicationError::invalid_section(
28 "extra data outside of any section",
29 ));
30 }
31 result.reverse();
32 Ok(result)
33}
34
35#[allow(dead_code)]
48pub fn encode_sections(sections: &[Vec<u8>]) -> VmResult<Vec<u8>> {
49 let mut out_len: usize = sections.iter().map(|section| section.len()).sum();
50 out_len += 4 * sections.len();
51 let mut out_data = Vec::with_capacity(out_len);
52 for section in sections {
53 let section_len = to_u32(section.len())?.to_be_bytes();
54 out_data.extend(section);
55 out_data.extend_from_slice(§ion_len);
56 }
57 debug_assert_eq!(out_data.len(), out_len);
58 debug_assert_eq!(out_data.capacity(), out_len);
59 Ok(out_data)
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn decode_sections_works_for_empty_sections() {
68 let dec = decode_sections(&[]).unwrap();
69 assert_eq!(dec.len(), 0);
70 let dec = decode_sections(b"\0\0\0\0").unwrap();
71 assert_eq!(dec, &[&[0u8; 0]]);
72 let dec = decode_sections(b"\0\0\0\0\0\0\0\0").unwrap();
73 assert_eq!(dec, &[&[0u8; 0]; 2]);
74 let dec = decode_sections(b"\0\0\0\0\0\0\0\0\0\0\0\0").unwrap();
75 assert_eq!(dec, &[&[0u8; 0]; 3]);
76 }
77
78 #[test]
79 fn decode_sections_works_for_one_element() {
80 let dec = decode_sections(b"\xAA\0\0\0\x01").unwrap();
81 assert_eq!(dec, &[vec![0xAA]]);
82 let dec = decode_sections(b"\xAA\xBB\0\0\0\x02").unwrap();
83 assert_eq!(dec, &[vec![0xAA, 0xBB]]);
84 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").unwrap();
85 assert_eq!(dec, &[vec![0x9D; 277]]);
86 }
87
88 #[test]
89 fn decode_sections_works_for_two_elements() {
90 let data = b"\xAA\0\0\0\x01\xBB\xCC\0\0\0\x02".to_vec();
91 assert_eq!(
92 decode_sections(&data).unwrap(),
93 &[vec![0xAA], vec![0xBB, 0xCC]]
94 );
95 let data = b"\xDE\xEF\x62\0\0\0\x03\0\0\0\0".to_vec();
96 assert_eq!(
97 decode_sections(&data).unwrap(),
98 &[vec![0xDE, 0xEF, 0x62], vec![]]
99 );
100 let data = b"\0\0\0\0\xDE\xEF\x62\0\0\0\x03".to_vec();
101 assert_eq!(
102 decode_sections(&data).unwrap(),
103 &[vec![], vec![0xDE, 0xEF, 0x62]]
104 );
105 let data = b"\0\0\0\0\0\0\0\0".to_vec();
106 assert_eq!(decode_sections(&data).unwrap(), &[vec![0u8; 0], vec![]]);
107 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();
108 assert_eq!(
109 decode_sections(&data).unwrap(),
110 &[vec![0xFF; 19], vec![0x9D; 277]]
111 );
112 }
113
114 #[test]
115 fn decode_sections_works_for_multiple_elements() {
116 let dec = decode_sections(b"\xAA\0\0\0\x01").unwrap();
117 assert_eq!(dec, &[vec![0xAA]]);
118 let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02").unwrap();
119 assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE]]);
120 let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0").unwrap();
121 assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE], vec![]]);
122 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").unwrap();
123 assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]);
124 }
125
126 #[test]
127 fn decode_sections_fails_for_invalid_length() {
128 assert!(decode_sections(b"\xAA\0\0\0\x02").is_err());
130 assert!(decode_sections(b"\xAA\0\0\0\x01\xBB\x03\0\0\0\x03").is_err());
132 }
133
134 #[test]
135 fn decode_sections_fails_for_extra_bytes() {
136 assert!(decode_sections(b"\x44\xAA\0\0\0\x01").is_err());
138 assert!(decode_sections(b"\x44\x44\xAA\0\0\0\x01").is_err());
139 assert!(decode_sections(b"\x44\x44\x44\xAA\0\0\0\x01").is_err());
140
141 assert!(decode_sections(b"\x44").is_err());
143 assert!(decode_sections(b"\x44\x44").is_err());
144 assert!(decode_sections(b"\x44\x44\x44").is_err());
145 }
146
147 #[test]
148 fn encode_sections_works_for_empty_sections() {
149 let enc = encode_sections(&[]).unwrap();
150 assert_eq!(enc, b"" as &[u8]);
151 let enc = encode_sections(&[vec![]]).unwrap();
152 assert_eq!(enc, b"\0\0\0\0" as &[u8]);
153 let enc = encode_sections(&[vec![], vec![]]).unwrap();
154 assert_eq!(enc, b"\0\0\0\0\0\0\0\0" as &[u8]);
155 let enc = encode_sections(&[vec![], vec![], vec![]]).unwrap();
156 assert_eq!(enc, b"\0\0\0\0\0\0\0\0\0\0\0\0" as &[u8]);
157 }
158
159 #[test]
160 fn encode_sections_works_for_one_element() {
161 let enc = encode_sections(&[]).unwrap();
162 assert_eq!(enc, b"" as &[u8]);
163 let enc = encode_sections(&[vec![0xAA]]).unwrap();
164 assert_eq!(enc, b"\xAA\0\0\0\x01" as &[u8]);
165 let enc = encode_sections(&[vec![0xAA, 0xBB]]).unwrap();
166 assert_eq!(enc, b"\xAA\xBB\0\0\0\x02" as &[u8]);
167 let enc = encode_sections(&[vec![0x9D; 277]]).unwrap();
168 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]);
169 }
170
171 #[test]
172 fn encode_sections_works_for_multiple_elements() {
173 let enc = encode_sections(&[vec![0xAA]]).unwrap();
174 assert_eq!(enc, b"\xAA\0\0\0\x01" as &[u8]);
175 let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE]]).unwrap();
176 assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02" as &[u8]);
177 let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![]]).unwrap();
178 assert_eq!(enc, b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0" as &[u8]);
179 let enc = encode_sections(&[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]).unwrap();
180 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]);
181 }
182}