1use crate::{BinaryReader, FromReader, Result, SectionLimited};
2
3/// A reader for the `metadata.code.branch_hint` custom section.
4pub type BranchHintSectionReader<'a> = SectionLimited<'a, BranchHintFunction<'a>>;
5
6/// Branch hints for a single function.
7///
8/// Produced from [`BranchHintSectionReader`].
9#[derive(Debug, Clone)]
10pub struct BranchHintFunction<'a> {
11 /// The function that these branch hints apply to.
12 pub func: u32,
13 /// The branch hints available for this function.
14 pub hints: SectionLimited<'a, BranchHint>,
15}
16
17impl<'a> FromReader<'a> for BranchHintFunction<'a> {
18 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
19 let func: u32 = reader.read_var_u32()?;
20 // FIXME(#188) ideally wouldn't have to do skips here
21 let hints: BinaryReader<'a> = reader.skip(|reader: &mut BinaryReader<'a>| {
22 let items_count: u32 = reader.read_var_u32()?;
23 for _ in 0..items_count {
24 reader.read::<BranchHint>()?;
25 }
26 Ok(())
27 })?;
28 Ok(BranchHintFunction {
29 func,
30 hints: SectionLimited::new(reader:hints)?,
31 })
32 }
33}
34
35/// A hint for a single branch.
36#[derive(Debug, Copy, Clone)]
37pub struct BranchHint {
38 /// The byte offset, from the start of the function's body, of where the
39 /// hinted instruction lives.
40 pub func_offset: u32,
41 /// Whether or not the branch is hinted to be taken or not.
42 pub taken: bool,
43}
44
45impl<'a> FromReader<'a> for BranchHint {
46 fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
47 let func_offset: u32 = reader.read_var_u32()?;
48 match reader.read_u8()? {
49 1 => {}
50 n: u8 => reader.invalid_leading_byte(byte:n, desc:"invalid branch hint byte")?,
51 }
52 let taken: bool = match reader.read_u8()? {
53 0 => false,
54 1 => true,
55 n: u8 => reader.invalid_leading_byte(byte:n, desc:"invalid branch hint taken byte")?,
56 };
57 Ok(BranchHint { func_offset, taken })
58 }
59}
60