baedeker_core/binary/
functionsec.rs1use alloc::vec::Vec;
10
11use crate::binary::leb128::{self, Cursor};
12use crate::binary::section::RawSection;
13use crate::error::{ByteOffset, DecodeContext, DecodeError, DecodeErrorKind};
14use crate::types::TypeIdx;
15
16pub fn parse_function_section(section: &RawSection<'_>) -> Result<Vec<TypeIdx>, DecodeError> {
17 let mut cursor = Cursor::new(section.data);
18 let count = leb128::decode_u32(&mut cursor).map_err(|mut e| {
19 e.context = DecodeContext::FunctionSection;
20 e.offset = ByteOffset(section.offset + e.offset.0);
21 e
22 })?;
23
24 let mut functions = Vec::with_capacity(cursor.capacity_hint(count));
25 for _ in 0..count {
26 let type_idx = leb128::decode_u32(&mut cursor).map_err(|mut e| {
27 e.context = DecodeContext::FunctionSection;
28 e.offset = ByteOffset(section.offset + e.offset.0);
29 e
30 })?;
31 functions.push(TypeIdx(type_idx));
32 }
33
34 if !cursor.is_empty() {
35 return Err(DecodeError {
36 offset: ByteOffset(section.offset + cursor.position()),
37 context: DecodeContext::FunctionSection,
38 kind: DecodeErrorKind::SectionSizeMismatch {
39 expected: section.data.len() as u32,
40 consumed: cursor.position() as u32,
41 },
42 });
43 }
44
45 Ok(functions)
46}
47
48#[cfg(test)]
49mod tests {
50 use alloc::vec;
51
52 use super::*;
53 use crate::binary::section::SectionId;
54
55 fn raw_function_section(data: &[u8]) -> RawSection<'_> {
56 RawSection {
57 id: SectionId::Function,
58 offset: 30,
59 data,
60 }
61 }
62
63 #[test]
64 fn parse_empty_function_section() {
65 let section = raw_function_section(&[0x00]);
66 let functions = parse_function_section(§ion).unwrap();
67 assert!(functions.is_empty());
68 }
69
70 #[test]
71 fn parse_function_type_indices() {
72 let section = raw_function_section(&[0x03, 0x00, 0x02, 0x7F]);
73 let functions = parse_function_section(§ion).unwrap();
74 assert_eq!(functions, vec![TypeIdx(0), TypeIdx(2), TypeIdx(127)]);
75 }
76
77 #[test]
78 fn reject_trailing_bytes() {
79 let section = raw_function_section(&[0x00, 0xFF]);
80 let err = parse_function_section(§ion).unwrap_err();
81 assert_eq!(
82 err.kind,
83 DecodeErrorKind::SectionSizeMismatch {
84 expected: 2,
85 consumed: 1,
86 }
87 );
88 }
89}