@@ -2,6 +2,8 @@ use anyhow::Result;
2
2
use indexmap:: { map:: Entry , IndexMap } ;
3
3
use serde:: Serialize ;
4
4
use std:: fmt;
5
+ use std:: mem;
6
+ use wasm_encoder:: { ComponentSection as _, ComponentSectionId , Encode , Section } ;
5
7
use wasmparser:: {
6
8
ComponentNameSectionReader , NameSectionReader , Parser , Payload :: * , ProducersSectionReader ,
7
9
} ;
@@ -222,125 +224,101 @@ fn rewrite_wasm(
222
224
add_producers : & Producers ,
223
225
input : & [ u8 ] ,
224
226
) -> Result < Vec < u8 > > {
225
- let mut parser = Parser :: new ( 0 ) . parse_all ( & input) ;
226
-
227
- enum Output {
228
- Component ( wasm_encoder:: Component ) ,
229
- Module ( wasm_encoder:: Module ) ,
230
- }
231
- impl Output {
232
- fn section (
233
- & mut self ,
234
- section : & ( impl wasm_encoder:: Section + wasm_encoder:: ComponentSection ) ,
235
- ) {
236
- match self {
237
- Output :: Component ( c) => {
238
- c. section ( section) ;
239
- }
240
- Output :: Module ( m) => {
241
- m. section ( section) ;
242
- }
243
- }
244
- }
245
- fn finish ( self ) -> Vec < u8 > {
246
- match self {
247
- Output :: Component ( c) => c. finish ( ) ,
248
- Output :: Module ( m) => m. finish ( ) ,
249
- }
250
- }
251
- }
252
-
253
- let mut output = match parser
254
- . next ( )
255
- . ok_or_else ( || anyhow:: anyhow!( "at least a version tag on binary" ) ) ??
256
- {
257
- Version {
258
- encoding : wasmparser:: Encoding :: Component ,
259
- ..
260
- } => Output :: Component ( wasm_encoder:: Component :: new ( ) ) ,
261
- Version {
262
- encoding : wasmparser:: Encoding :: Module ,
263
- ..
264
- } => Output :: Module ( wasm_encoder:: Module :: new ( ) ) ,
265
- _ => {
266
- panic ! ( "first item from parser must be a Version tag" )
267
- }
268
- } ;
269
-
270
227
let mut producers_found = false ;
271
228
let mut names_found = false ;
272
- let mut depth = 0 ;
273
- for payload in parser {
229
+ let mut stack = Vec :: new ( ) ;
230
+ let mut output = Vec :: new ( ) ;
231
+ for payload in Parser :: new ( 0 ) . parse_all ( & input) {
274
232
let payload = payload?;
275
233
276
234
// Track nesting depth, so that we don't mess with inner producer sections:
277
235
match payload {
278
- ModuleSection { .. } | ComponentSection { .. } => depth += 1 ,
279
- End { .. } => depth -= 1 ,
236
+ Version { encoding, .. } => {
237
+ output. extend_from_slice ( match encoding {
238
+ wasmparser:: Encoding :: Component => & wasm_encoder:: Component :: HEADER ,
239
+ wasmparser:: Encoding :: Module => & wasm_encoder:: Module :: HEADER ,
240
+ } ) ;
241
+ }
242
+ ModuleSection { .. } | ComponentSection { .. } => {
243
+ stack. push ( mem:: take ( & mut output) ) ;
244
+ continue ;
245
+ }
246
+ End { .. } => {
247
+ let mut parent = match stack. pop ( ) {
248
+ Some ( c) => c,
249
+ None => break ,
250
+ } ;
251
+ if output. starts_with ( & wasm_encoder:: Component :: HEADER ) {
252
+ parent. push ( ComponentSectionId :: Component as u8 ) ;
253
+ output. encode ( & mut parent) ;
254
+ } else {
255
+ parent. push ( ComponentSectionId :: CoreModule as u8 ) ;
256
+ output. encode ( & mut parent) ;
257
+ }
258
+ output = parent;
259
+ }
280
260
_ => { }
281
261
}
282
262
283
263
// Process the wasm sections:
284
264
match payload {
285
265
// Only rewrite the outermost producers section:
286
- CustomSection ( c) if c. name ( ) == "producers" && depth == 0 => {
266
+ CustomSection ( c) if c. name ( ) == "producers" && stack . len ( ) == 0 => {
287
267
producers_found = true ;
288
268
let section = ProducersSectionReader :: new ( c. data ( ) , c. data_offset ( ) ) ?;
289
269
let mut producers = Producers :: from_reader ( section) ?;
290
270
// Add to the section according to the command line flags:
291
271
producers. merge ( & add_producers) ;
292
272
// Encode into output:
293
- output . section ( & producers. section ( ) ) ;
273
+ producers. section ( ) . append_to ( & mut output ) ;
294
274
}
295
275
296
- CustomSection ( c) if c. name ( ) == "name" && depth == 0 => {
276
+ CustomSection ( c) if c. name ( ) == "name" && stack . len ( ) == 0 => {
297
277
names_found = true ;
298
278
let section = NameSectionReader :: new ( c. data ( ) , c. data_offset ( ) ) ;
299
279
let mut names = ModuleNames :: from_reader ( section) ?;
300
280
names. merge ( & ModuleNames :: from_name ( add_name) ) ;
301
281
302
- output . section ( & names. section ( ) ?. as_custom ( ) ) ;
282
+ names. section ( ) ?. as_custom ( ) . append_to ( & mut output ) ;
303
283
}
304
284
305
- CustomSection ( c) if c. name ( ) == "component-name" && depth == 0 => {
285
+ CustomSection ( c) if c. name ( ) == "component-name" && stack . len ( ) == 0 => {
306
286
names_found = true ;
307
287
let section = ComponentNameSectionReader :: new ( c. data ( ) , c. data_offset ( ) ) ;
308
288
let mut names = ComponentNames :: from_reader ( section) ?;
309
289
names. merge ( & ComponentNames :: from_name ( add_name) ) ;
310
- output . section ( & names. section ( ) ?. as_custom ( ) ) ;
290
+ names. section ( ) ?. as_custom ( ) . append_to ( & mut output ) ;
311
291
}
312
292
313
293
// All other sections get passed through unmodified:
314
294
_ => {
315
295
if let Some ( ( id, range) ) = payload. as_section ( ) {
316
- output . section ( & wasm_encoder:: RawSection {
296
+ wasm_encoder:: RawSection {
317
297
id,
318
298
data : & input[ range] ,
319
- } ) ;
299
+ }
300
+ . append_to ( & mut output) ;
320
301
}
321
302
}
322
303
}
323
304
}
324
305
if !names_found && add_name. is_some ( ) {
325
- match & mut output {
326
- Output :: Component ( c) => {
327
- let names = ComponentNames :: from_name ( add_name) ;
328
- c. section ( & names. section ( ) ?) ;
329
- }
330
- Output :: Module ( m) => {
331
- let names = ModuleNames :: from_name ( add_name) ;
332
- m. section ( & names. section ( ) ?) ;
333
- }
306
+ if output. starts_with ( & wasm_encoder:: Component :: HEADER ) {
307
+ let names = ComponentNames :: from_name ( add_name) ;
308
+ names. section ( ) ?. append_to_component ( & mut output) ;
309
+ } else {
310
+ let names = ModuleNames :: from_name ( add_name) ;
311
+ names. section ( ) ?. append_to ( & mut output)
334
312
}
335
313
}
336
314
if !producers_found && !add_producers. is_empty ( ) {
337
315
let mut producers = Producers :: empty ( ) ;
338
316
// Add to the section according to the command line flags:
339
317
producers. merge ( add_producers) ;
340
318
// Encode into output:
341
- output . section ( & producers. section ( ) ) ;
319
+ producers. section ( ) . append_to ( & mut output ) ;
342
320
}
343
- Ok ( output. finish ( ) )
321
+ Ok ( output)
344
322
}
345
323
346
324
/// A tree of the metadata found in a WebAssembly binary.
0 commit comments