1use crate::{
4 artifact::{
5 Artifact, ArtifactData, ArtifactLocal, ArtifactMemory, ArtifactNamedImport,
6 ArtifactVersion, CompiledFunctionBytes, InstantiatedGlobals, InstantiatedTable,
7 },
8 parse::*,
9 types::{BlockType, FuncIndex, FunctionType, GlobalInit, Name, TypeIndex, ValueType},
10};
11use anyhow::{bail, Context};
12use std::{collections::BTreeMap, io::Cursor};
13
14impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ArtifactLocal {
15 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
16 let multiplicity = cursor.next(ctx)?;
17 let ty = cursor.next(ctx)?;
18 Ok(ArtifactLocal {
19 multiplicity,
20 ty,
21 })
22 }
23}
24
25impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ArtifactNamedImport {
26 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
27 let mod_name = cursor.next(ctx)?;
28 let item_name = cursor.next(ctx)?;
29 let ty = cursor.next(ctx)?;
30 Ok(ArtifactNamedImport {
31 mod_name,
32 item_name,
33 ty,
34 })
35 }
36}
37
38impl<'a, Ctx: Copy> Parseable<'a, Ctx> for InstantiatedGlobals {
39 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
40 let len = u32::parse(ctx, cursor)?;
41 let mut inits = Vec::with_capacity(len as usize);
42 for _ in 0..len {
43 match Byte::parse(ctx, cursor)? {
44 0 => {
45 inits.push(GlobalInit::I32(cursor.next(ctx)?));
46 }
47 1 => {
48 inits.push(GlobalInit::I64(cursor.next(ctx)?));
49 }
50 _ => bail!("Unsupported global init tag."),
51 }
52 }
53 Ok(InstantiatedGlobals {
54 inits,
55 })
56 }
57}
58
59impl<'a, Ctx: Copy> Parseable<'a, Ctx> for CompiledFunctionBytes<'a> {
60 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
61 let type_idx = TypeIndex::parse(ctx, cursor).context("Failed to parse type type index.")?;
62 let return_type = BlockType::parse(ctx, cursor).context("Failed to parse return type.")?;
63 let params: &'a [ValueType] =
64 cursor.next(ctx).context("Failed to parse parameter type.")?;
65 let num_locals: u32 = cursor.next(ctx).context("Failed to parse number of locals.")?;
66 let locals: Vec<ArtifactLocal> = cursor.next(ctx).context("Failed to parse locals.")?;
67 let num_registers: u32 = cursor.next(ctx).context("Failed to registers.")?;
68 let constants: Vec<i64> = cursor.next(ctx).context("Failed to parse constants.")?;
69 let code = cursor.next(ctx)?;
70 Ok(CompiledFunctionBytes {
71 type_idx,
72 return_type,
73 params,
74 num_locals,
75 locals,
76 num_registers,
77 constants,
78 code,
79 })
80 }
81}
82
83impl<'a, Ctx: Copy> Parseable<'a, Ctx> for InstantiatedTable {
84 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
85 let functions = cursor.next(ctx)?;
86 Ok(InstantiatedTable {
87 functions,
88 })
89 }
90}
91
92impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ArtifactMemory {
93 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
94 let init_size = cursor.next(ctx)?;
95 let max_size = cursor.next(ctx)?;
96 let init = Vec::<ArtifactData>::parse(ctx, cursor)?;
97 Ok(ArtifactMemory {
98 init_size,
99 max_size,
100 init,
101 })
102 }
103}
104
105impl<'a, Ctx: Copy> Parseable<'a, Ctx> for ArtifactData {
106 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
107 let offset = cursor.next(ctx)?;
108 let init = cursor.next(ctx)?;
109 Ok(Self {
110 offset,
111 init,
112 })
113 }
114}
115
116impl<'a, Ctx> Parseable<'a, Ctx> for ArtifactVersion {
117 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
118 let v: u8 = cursor.next(ctx)?;
119 match v {
120 255 => Ok(Self::V1),
121 n => anyhow::bail!("Unsupported artifact version: {n}."),
122 }
123 }
124}
125
126impl<'a, Ctx: Copy, I: Parseable<'a, Ctx>> Parseable<'a, Ctx>
130 for Artifact<I, CompiledFunctionBytes<'a>>
131{
132 fn parse(ctx: Ctx, cursor: &mut Cursor<&'a [u8]>) -> ParseResult<Self> {
133 let version = cursor.next(ctx)?;
134 let imports: Vec<I> = {
135 let imports_len: u16 = cursor.next(ctx)?;
136 let mut imports = Vec::with_capacity(imports_len.into());
137 for _ in 0..imports_len {
138 imports.push(cursor.next(ctx)?)
139 }
140 imports
141 };
142 let ty: Vec<FunctionType> = Vec::parse(ctx, cursor).context("Failed to parse types.")?;
143 let table = InstantiatedTable::parse(ctx, cursor).context("Failed to parse table.")?;
144 let memory = cursor.next(ctx).context("Failed to parse memory.")?;
145 let global = InstantiatedGlobals::parse(ctx, cursor).context("Failed to parse globals.")?;
146 let export_len = u32::parse(ctx, cursor).context("Failed to parse export_len.")?;
147 let mut export = BTreeMap::new();
148 for _ in 0..export_len {
149 let name = Name::parse(ctx, cursor)?;
150 let idx = FuncIndex::parse(ctx, cursor)?;
151 if export.insert(name, idx).is_some() {
152 bail!("Duplicate names in export list. This should not happen in artifacts.")
153 }
154 }
155 let code = Vec::parse(ctx, cursor).context("Failed to parse code.")?;
156 Ok(Artifact {
157 version,
158 imports,
159 ty,
160 table,
161 memory,
162 global,
163 export,
164 code,
165 })
166 }
167}