14
14
*/
15
15
16
16
use std:: boxed:: Box ;
17
+ use std:: convert:: TryInto ;
17
18
use std:: str;
18
19
use std:: vec:: Vec ;
19
20
@@ -38,36 +39,43 @@ fn is_name_prefix(name: &str, prefix: &'static str) -> bool {
38
39
name. starts_with ( prefix)
39
40
}
40
41
41
- const WASM_MAGIC_NUMBER : u32 = 0x6d736100 ;
42
+ const WASM_MAGIC_NUMBER : & ' static [ u8 ; 4 ] = b" \0 asm" ;
42
43
const WASM_EXPERIMENTAL_VERSION : u32 = 0xd ;
43
44
const WASM_SUPPORTED_VERSION : u32 = 0x1 ;
44
45
45
- pub struct SectionHeader < ' a > {
46
+ pub ( crate ) struct SectionHeader < ' a > {
46
47
pub code : SectionCode < ' a > ,
47
48
pub payload_start : usize ,
48
49
pub payload_len : usize ,
49
50
}
50
51
51
52
/// Bytecode range in the WebAssembly module.
52
- #[ derive( Debug , Copy , Clone ) ]
53
+ #[ derive( Copy , Clone , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
53
54
pub struct Range {
55
+ /// The start bound of the range.
54
56
pub start : usize ,
57
+ /// The end bound of the range.
55
58
pub end : usize ,
56
59
}
57
60
58
61
impl Range {
62
+ /// Constructs a new instance of `Range`.
63
+ ///
64
+ /// # Panics
65
+ /// If `start` is greater than `end`.
59
66
pub fn new ( start : usize , end : usize ) -> Range {
60
67
assert ! ( start <= end) ;
61
68
Range { start, end }
62
69
}
63
70
71
+ /// Returns a new slice between `start` and `end - 1` from `data`.
64
72
pub fn slice < ' a > ( & self , data : & ' a [ u8 ] ) -> & ' a [ u8 ] {
65
73
& data[ self . start ..self . end ]
66
74
}
67
75
}
68
76
69
77
/// A binary reader of the WebAssembly structures and types.
70
- #[ derive( Clone ) ]
78
+ #[ derive( Clone , Debug ) ]
71
79
pub struct BinaryReader < ' a > {
72
80
pub ( crate ) buffer : & ' a [ u8 ] ,
73
81
pub ( crate ) position : usize ,
@@ -94,6 +102,7 @@ impl<'a> BinaryReader<'a> {
94
102
}
95
103
}
96
104
105
+ /// Constructs a `BinaryReader` with an explicit starting offset.
97
106
pub fn new_with_offset ( data : & [ u8 ] , original_offset : usize ) -> BinaryReader {
98
107
BinaryReader {
99
108
buffer : data,
@@ -106,6 +115,7 @@ impl<'a> BinaryReader<'a> {
106
115
self . original_offset + self . position
107
116
}
108
117
118
+ /// Returns a range from the starting offset to the end of the buffer.
109
119
pub fn range ( & self ) -> Range {
110
120
Range {
111
121
start : self . original_offset ,
@@ -374,48 +384,77 @@ impl<'a> BinaryReader<'a> {
374
384
} )
375
385
}
376
386
387
+ /// Returns whether the `BinaryReader` has reached the end of the file.
377
388
pub fn eof ( & self ) -> bool {
378
389
self . position >= self . buffer . len ( )
379
390
}
380
391
392
+ /// Returns the `BinaryReader`'s current position.
381
393
pub fn current_position ( & self ) -> usize {
382
394
self . position
383
395
}
384
396
397
+ /// Returns the number of bytes remaining in the `BinaryReader`.
385
398
pub fn bytes_remaining ( & self ) -> usize {
386
399
self . buffer . len ( ) - self . position
387
400
}
388
401
402
+ /// Advances the `BinaryReader` `size` bytes, and returns a slice from the
403
+ /// current position of `size` length.
404
+ ///
405
+ /// # Errors
406
+ /// If `size` exceeds the remaining length in `BinaryReader`.
389
407
pub fn read_bytes ( & mut self , size : usize ) -> Result < & ' a [ u8 ] > {
390
408
self . ensure_has_bytes ( size) ?;
391
409
let start = self . position ;
392
410
self . position += size;
393
411
Ok ( & self . buffer [ start..self . position ] )
394
412
}
395
413
414
+ /// Advances the `BinaryReader` four bytes and returns a `u32`.
415
+ /// # Errors
416
+ /// If `BinaryReader` has less than four bytes remaining.
396
417
pub fn read_u32 ( & mut self ) -> Result < u32 > {
397
418
self . ensure_has_bytes ( 4 ) ?;
398
- let b1 = u32:: from ( self . buffer [ self . position ] ) ;
399
- let b2 = u32:: from ( self . buffer [ self . position + 1 ] ) ;
400
- let b3 = u32:: from ( self . buffer [ self . position + 2 ] ) ;
401
- let b4 = u32:: from ( self . buffer [ self . position + 3 ] ) ;
419
+ let word = u32:: from_le_bytes (
420
+ self . buffer [ self . position ..self . position + 4 ]
421
+ . try_into ( )
422
+ . unwrap ( ) ,
423
+ ) ;
402
424
self . position += 4 ;
403
- Ok ( b1 | ( b2 << 8 ) | ( b3 << 16 ) | ( b4 << 24 ) )
425
+ Ok ( word )
404
426
}
405
427
428
+ /// Advances the `BinaryReader` eight bytes and returns a `u64`.
429
+ /// # Errors
430
+ /// If `BinaryReader` has less than eight bytes remaining.
406
431
pub fn read_u64 ( & mut self ) -> Result < u64 > {
407
- let w1 = u64:: from ( self . read_u32 ( ) ?) ;
408
- let w2 = u64:: from ( self . read_u32 ( ) ?) ;
409
- Ok ( w1 | ( w2 << 32 ) )
432
+ self . ensure_has_bytes ( 8 ) ?;
433
+ let word = u64:: from_le_bytes (
434
+ self . buffer [ self . position ..self . position + 8 ]
435
+ . try_into ( )
436
+ . unwrap ( ) ,
437
+ ) ;
438
+ self . position += 8 ;
439
+ Ok ( word)
410
440
}
411
441
442
+ /// Advances the `BinaryReader` a single byte, and returns the data as
443
+ /// a `u32`.
444
+ /// # Errors
445
+ /// If `BinaryReader` has no bytes remaining.
412
446
pub fn read_u8 ( & mut self ) -> Result < u32 > {
413
447
self . ensure_has_byte ( ) ?;
414
448
let b = u32:: from ( self . buffer [ self . position ] ) ;
415
449
self . position += 1 ;
416
450
Ok ( b)
417
451
}
418
452
453
+ /// Advances the `BinaryReader` up to two bytes to parse a variable
454
+ /// length integer as a `u8`.
455
+ /// # Errors
456
+ /// If `BinaryReader` has less than one or two bytes remaining, or the
457
+ /// integer is larger than eight bits.
419
458
pub fn read_var_u8 ( & mut self ) -> Result < u32 > {
420
459
// Optimization for single byte i32.
421
460
let byte = self . read_u8 ( ) ?;
@@ -433,6 +472,11 @@ impl<'a> BinaryReader<'a> {
433
472
Ok ( result)
434
473
}
435
474
475
+ /// Advances the `BinaryReader` up to four bytes to parse a variable
476
+ /// length integer as a `u32`.
477
+ /// # Errors
478
+ /// If `BinaryReader` has less than one or up to four bytes remaining, or
479
+ /// the integer is larger than 32 bits.
436
480
pub fn read_var_u32 ( & mut self ) -> Result < u32 > {
437
481
// Optimization for single byte i32.
438
482
let byte = self . read_u8 ( ) ?;
@@ -460,6 +504,11 @@ impl<'a> BinaryReader<'a> {
460
504
Ok ( result)
461
505
}
462
506
507
+ /// Advances the `BinaryReader` up to four bytes over a variable length 32
508
+ /// bit integer, discarding the result.
509
+ /// # Errors
510
+ /// If `BinaryReader` has less than one or up to four bytes remaining, or
511
+ /// the integer is larger than 32 bits.
463
512
pub fn skip_var_32 ( & mut self ) -> Result < ( ) > {
464
513
for _ in 0 ..5 {
465
514
let byte = self . read_u8 ( ) ?;
@@ -473,16 +522,26 @@ impl<'a> BinaryReader<'a> {
473
522
} )
474
523
}
475
524
525
+ /// Alias method for `BinaryReader::skip_var_u32`.
476
526
pub fn skip_type ( & mut self ) -> Result < ( ) > {
477
527
self . skip_var_32 ( )
478
528
}
479
529
530
+ /// Advances the `BinaryReader` `len` bytes, skipping the result.
531
+ /// # Errors
532
+ /// If `BinaryReader` has less than `len` bytes remaining.
480
533
pub fn skip_bytes ( & mut self , len : usize ) -> Result < ( ) > {
481
534
self . ensure_has_bytes ( len) ?;
482
535
self . position += len;
483
536
Ok ( ( ) )
484
537
}
485
538
539
+ /// Advances the `BinaryReader` past a WebAssembly string. This method does
540
+ /// not perform any utf-8 validation.
541
+ /// # Errors
542
+ /// If `BinaryReader` has less than four bytes, the string's length exceeds
543
+ /// the remaining bytes, or the string length
544
+ /// exceeds `limits::MAX_WASM_STRING_SIZE`.
486
545
pub fn skip_string ( & mut self ) -> Result < ( ) > {
487
546
let len = self . read_var_u32 ( ) ? as usize ;
488
547
if len > MAX_WASM_STRING_SIZE {
@@ -502,6 +561,11 @@ impl<'a> BinaryReader<'a> {
502
561
self . position = position;
503
562
}
504
563
564
+ /// Advances the `BinaryReader` up to four bytes to parse a variable
565
+ /// length integer as a `i32`.
566
+ /// # Errors
567
+ /// If `BinaryReader` has less than one or up to four bytes remaining, or
568
+ /// the integer is larger than 32 bits.
505
569
pub fn read_var_i32 ( & mut self ) -> Result < i32 > {
506
570
// Optimization for single byte i32.
507
571
let byte = self . read_u8 ( ) ?;
@@ -534,6 +598,11 @@ impl<'a> BinaryReader<'a> {
534
598
Ok ( ( result << ashift) >> ashift)
535
599
}
536
600
601
+ /// Advances the `BinaryReader` up to four bytes to parse a variable
602
+ /// length integer as a signed 33 bit integer, returned as a `i64`.
603
+ /// # Errors
604
+ /// If `BinaryReader` has less than one or up to five bytes remaining, or
605
+ /// the integer is larger than 33 bits.
537
606
pub fn read_var_s33 ( & mut self ) -> Result < i64 > {
538
607
// Optimization for single byte.
539
608
let byte = self . read_u8 ( ) ?;
@@ -551,7 +620,7 @@ impl<'a> BinaryReader<'a> {
551
620
let sign_and_unused_bit = ( byte << 1 ) as i8 >> ( 33 - shift) ;
552
621
if continuation_bit || ( sign_and_unused_bit != 0 && sign_and_unused_bit != -1 ) {
553
622
return Err ( BinaryReaderError {
554
- message : "Invalid var_i33 " ,
623
+ message : "Invalid var_s33 " ,
555
624
offset : self . original_position ( ) - 1 ,
556
625
} ) ;
557
626
}
@@ -566,6 +635,11 @@ impl<'a> BinaryReader<'a> {
566
635
Ok ( ( result << ashift) >> ashift)
567
636
}
568
637
638
+ /// Advances the `BinaryReader` up to eight bytes to parse a variable
639
+ /// length integer as a 64 bit integer, returned as a `i64`.
640
+ /// # Errors
641
+ /// If `BinaryReader` has less than one or up to eight bytes remaining, or
642
+ /// the integer is larger than 64 bits.
569
643
pub fn read_var_i64 ( & mut self ) -> Result < i64 > {
570
644
let mut result: i64 = 0 ;
571
645
let mut shift = 0 ;
@@ -592,16 +666,31 @@ impl<'a> BinaryReader<'a> {
592
666
Ok ( ( result << ashift) >> ashift)
593
667
}
594
668
669
+ /// Advances the `BinaryReader` up to four bytes to parse a variable
670
+ /// length integer as a 32 bit floating point integer, returned as `Ieee32`.
671
+ /// # Errors
672
+ /// If `BinaryReader` has less than one or up to four bytes remaining, or
673
+ /// the integer is larger than 32 bits.
595
674
pub fn read_f32 ( & mut self ) -> Result < Ieee32 > {
596
675
let value = self . read_u32 ( ) ?;
597
676
Ok ( Ieee32 ( value) )
598
677
}
599
678
679
+ /// Advances the `BinaryReader` up to four bytes to parse a variable
680
+ /// length integer as a 32 bit floating point integer, returned as `Ieee32`.
681
+ /// # Errors
682
+ /// If `BinaryReader` has less than one or up to four bytes remaining, or
683
+ /// the integer is larger than 32 bits.
600
684
pub fn read_f64 ( & mut self ) -> Result < Ieee64 > {
601
685
let value = self . read_u64 ( ) ?;
602
686
Ok ( Ieee64 ( value) )
603
687
}
604
688
689
+ /// Reads a WebAssembly string from the module.
690
+ /// # Errors
691
+ /// If `BinaryReader` has less than up to four bytes remaining, the string's
692
+ /// length exceeds the remaining bytes, the string's length exceeds
693
+ /// `limits::MAX_WASM_STRING_SIZE`, or the string contains invalid utf-8.
605
694
pub fn read_string ( & mut self ) -> Result < & ' a str > {
606
695
let len = self . read_var_u32 ( ) ? as usize ;
607
696
if len > MAX_WASM_STRING_SIZE {
@@ -859,6 +948,10 @@ impl<'a> BinaryReader<'a> {
859
948
}
860
949
}
861
950
951
+ /// Reads the next available `Operator`.
952
+ /// # Errors
953
+ /// If `BinaryReader` has less bytes remaining than required to parse
954
+ /// the `Operator`.
862
955
pub fn read_operator ( & mut self ) -> Result < Operator < ' a > > {
863
956
let code = self . read_u8 ( ) ? as u8 ;
864
957
Ok ( match code {
@@ -1442,8 +1535,8 @@ impl<'a> BinaryReader<'a> {
1442
1535
0xc0 => Operator :: V8x16Swizzle ,
1443
1536
0x03 | 0xc1 => {
1444
1537
let mut lanes = [ 0 as SIMDLaneIndex ; 16 ] ;
1445
- for i in 0 .. 16 {
1446
- lanes [ i ] = self . read_lane_index ( 32 ) ?
1538
+ for lane in & mut lanes {
1539
+ * lane = self . read_lane_index ( 32 ) ?
1447
1540
}
1448
1541
Operator :: V8x16Shuffle { lanes }
1449
1542
}
@@ -1469,7 +1562,7 @@ impl<'a> BinaryReader<'a> {
1469
1562
}
1470
1563
1471
1564
pub ( crate ) fn read_file_header ( & mut self ) -> Result < u32 > {
1472
- let magic_number = self . read_u32 ( ) ?;
1565
+ let magic_number = self . read_bytes ( 4 ) ?;
1473
1566
if magic_number != WASM_MAGIC_NUMBER {
1474
1567
return Err ( BinaryReaderError {
1475
1568
message : "Bad magic number" ,
@@ -1560,6 +1653,11 @@ impl<'a> BrTable<'a> {
1560
1653
self . cnt
1561
1654
}
1562
1655
1656
+ /// Returns whether `BrTable` doesn't have any labels apart from the default one.
1657
+ pub fn is_empty ( & self ) -> bool {
1658
+ self . len ( ) == 0
1659
+ }
1660
+
1563
1661
/// Reads br_table entries.
1564
1662
///
1565
1663
/// # Examples
@@ -1602,6 +1700,7 @@ impl<'a> BrTable<'a> {
1602
1700
/// }
1603
1701
/// }
1604
1702
/// ```
1703
+ #[ derive( Clone , Debug ) ]
1605
1704
pub struct BrTableIterator < ' a > {
1606
1705
reader : BinaryReader < ' a > ,
1607
1706
}
0 commit comments