1use getset::Getters;
2use scroll::{ctx, Uleb128};
3
4use crate::error;
5
6#[allow(dead_code)]
8#[derive(Debug, Getters, Default)]
9#[get = "pub"]
10struct TryBlock {
11 start_pc: u64,
13 length: u64,
15 num_catches: u64,
17 catch_blocks: Vec<(CatchBlock, usize)>,
19}
20
21impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for TryBlock {
22 type Error = error::Error;
23 fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
24 let off = &mut 0;
25 let start_pc = Uleb128::read(source, off).unwrap();
26 let length = Uleb128::read(source, off).unwrap();
27 let num_catches = Uleb128::read(source, off).unwrap();
28
29 let catch_blocks = (0..num_catches)
30 .map(|_| CatchBlock::try_from_ctx(source, scroll::Endian::Little))
31 .collect::<Result<Vec<_>, _>>()?;
32
33 Ok((
34 TryBlock {
35 start_pc,
36 length,
37 num_catches,
38 catch_blocks,
39 },
40 source.len(),
41 ))
42 }
43}
44
45#[allow(dead_code)]
47#[derive(Debug, Getters, Default)]
48#[get = "pub"]
49struct CatchBlock {
50 type_idx: u64,
52 handler_pc: u64,
54 catch_type: u64,
56}
57
58impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for CatchBlock {
59 type Error = error::Error;
60 fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
61 let off = &mut 0;
62 let type_idx = Uleb128::read(source, off).unwrap();
63 let handler_pc = Uleb128::read(source, off).unwrap();
64 let catch_type = Uleb128::read(source, off).unwrap();
65
66 Ok((
67 CatchBlock {
68 type_idx,
69 handler_pc,
70 catch_type,
71 },
72 source.len(),
73 ))
74 }
75}
76
77#[derive(Debug, Getters, Default)]
78#[get = "pub"]
79pub struct Code {
80 num_regs: u64,
82 num_args: u64,
84 code_size: u64,
86 tries_size: u64,
88 instructions: Vec<u8>,
90 try_blocks: Vec<(TryBlock, usize)>,
92}
93
94impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Code {
95 type Error = error::Error;
96 fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
97 let off = &mut 0;
98
99 let num_regs = Uleb128::read(source, off).unwrap();
100 let num_args = Uleb128::read(source, off).unwrap();
101 let code_size = Uleb128::read(source, off).unwrap();
102 let tries_size = Uleb128::read(source, off).unwrap();
103
104 tracing::debug!(
105 "num_regs: {}, num_args: {}, code_size: {}, tries_size: {}",
106 num_regs,
107 num_args,
108 code_size,
109 tries_size
110 );
111
112 let instructions = source[*off..*off + code_size as usize].to_vec();
113 *off += code_size as usize;
114
115 let try_blocks = (0..tries_size)
116 .map(|_| TryBlock::try_from_ctx(source, scroll::Endian::Little))
117 .collect::<Result<Vec<_>, _>>()?;
118
119 Ok((
120 Code {
121 num_regs,
122 num_args,
123 code_size,
124 tries_size,
125 instructions,
126 try_blocks,
127 },
128 source.len(),
129 ))
130 }
131}