1414 */
1515
1616use std:: boxed:: Box ;
17+ use std:: convert:: TryInto ;
1718use std:: str;
1819use std:: vec:: Vec ;
1920
@@ -38,36 +39,43 @@ fn is_name_prefix(name: &str, prefix: &'static str) -> bool {
3839 name. starts_with ( prefix)
3940}
4041
41- const WASM_MAGIC_NUMBER : u32 = 0x6d736100 ;
42+ const WASM_MAGIC_NUMBER : & ' static [ u8 ; 4 ] = b" \0 asm" ;
4243const WASM_EXPERIMENTAL_VERSION : u32 = 0xd ;
4344const WASM_SUPPORTED_VERSION : u32 = 0x1 ;
4445
45- pub struct SectionHeader < ' a > {
46+ pub ( crate ) struct SectionHeader < ' a > {
4647 pub code : SectionCode < ' a > ,
4748 pub payload_start : usize ,
4849 pub payload_len : usize ,
4950}
5051
5152/// Bytecode range in the WebAssembly module.
52- #[ derive( Debug , Copy , Clone ) ]
53+ #[ derive( Copy , Clone , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
5354pub struct Range {
55+ /// The start bound of the range.
5456 pub start : usize ,
57+ /// The end bound of the range.
5558 pub end : usize ,
5659}
5760
5861impl Range {
62+ /// Constructs a new instance of `Range`.
63+ ///
64+ /// # Panics
65+ /// If `start` is greater than `end`.
5966 pub fn new ( start : usize , end : usize ) -> Range {
6067 assert ! ( start <= end) ;
6168 Range { start, end }
6269 }
6370
71+ /// Returns a new slice between `start` and `end - 1` from `data`.
6472 pub fn slice < ' a > ( & self , data : & ' a [ u8 ] ) -> & ' a [ u8 ] {
6573 & data[ self . start ..self . end ]
6674 }
6775}
6876
6977/// A binary reader of the WebAssembly structures and types.
70- #[ derive( Clone ) ]
78+ #[ derive( Clone , Debug ) ]
7179pub struct BinaryReader < ' a > {
7280 pub ( crate ) buffer : & ' a [ u8 ] ,
7381 pub ( crate ) position : usize ,
@@ -94,6 +102,7 @@ impl<'a> BinaryReader<'a> {
94102 }
95103 }
96104
105+ /// Constructs a `BinaryReader` with an explicit starting offset.
97106 pub fn new_with_offset ( data : & [ u8 ] , original_offset : usize ) -> BinaryReader {
98107 BinaryReader {
99108 buffer : data,
@@ -106,6 +115,7 @@ impl<'a> BinaryReader<'a> {
106115 self . original_offset + self . position
107116 }
108117
118+ /// Returns a range from the starting offset to the end of the buffer.
109119 pub fn range ( & self ) -> Range {
110120 Range {
111121 start : self . original_offset ,
@@ -374,48 +384,77 @@ impl<'a> BinaryReader<'a> {
374384 } )
375385 }
376386
387+ /// Returns whether the `BinaryReader` has reached the end of the file.
377388 pub fn eof ( & self ) -> bool {
378389 self . position >= self . buffer . len ( )
379390 }
380391
392+ /// Returns the `BinaryReader`'s current position.
381393 pub fn current_position ( & self ) -> usize {
382394 self . position
383395 }
384396
397+ /// Returns the number of bytes remaining in the `BinaryReader`.
385398 pub fn bytes_remaining ( & self ) -> usize {
386399 self . buffer . len ( ) - self . position
387400 }
388401
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`.
389407 pub fn read_bytes ( & mut self , size : usize ) -> Result < & ' a [ u8 ] > {
390408 self . ensure_has_bytes ( size) ?;
391409 let start = self . position ;
392410 self . position += size;
393411 Ok ( & self . buffer [ start..self . position ] )
394412 }
395413
414+ /// Advances the `BinaryReader` four bytes and returns a `u32`.
415+ /// # Errors
416+ /// If `BinaryReader` has less than four bytes remaining.
396417 pub fn read_u32 ( & mut self ) -> Result < u32 > {
397418 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+ ) ;
402424 self . position += 4 ;
403- Ok ( b1 | ( b2 << 8 ) | ( b3 << 16 ) | ( b4 << 24 ) )
425+ Ok ( word )
404426 }
405427
428+ /// Advances the `BinaryReader` eight bytes and returns a `u64`.
429+ /// # Errors
430+ /// If `BinaryReader` has less than eight bytes remaining.
406431 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)
410440 }
411441
442+ /// Advances the `BinaryReader` a single byte, and returns the data as
443+ /// a `u32`.
444+ /// # Errors
445+ /// If `BinaryReader` has no bytes remaining.
412446 pub fn read_u8 ( & mut self ) -> Result < u32 > {
413447 self . ensure_has_byte ( ) ?;
414448 let b = u32:: from ( self . buffer [ self . position ] ) ;
415449 self . position += 1 ;
416450 Ok ( b)
417451 }
418452
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.
419458 pub fn read_var_u8 ( & mut self ) -> Result < u32 > {
420459 // Optimization for single byte i32.
421460 let byte = self . read_u8 ( ) ?;
@@ -433,6 +472,11 @@ impl<'a> BinaryReader<'a> {
433472 Ok ( result)
434473 }
435474
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.
436480 pub fn read_var_u32 ( & mut self ) -> Result < u32 > {
437481 // Optimization for single byte i32.
438482 let byte = self . read_u8 ( ) ?;
@@ -460,6 +504,11 @@ impl<'a> BinaryReader<'a> {
460504 Ok ( result)
461505 }
462506
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.
463512 pub fn skip_var_32 ( & mut self ) -> Result < ( ) > {
464513 for _ in 0 ..5 {
465514 let byte = self . read_u8 ( ) ?;
@@ -473,16 +522,26 @@ impl<'a> BinaryReader<'a> {
473522 } )
474523 }
475524
525+ /// Alias method for `BinaryReader::skip_var_u32`.
476526 pub fn skip_type ( & mut self ) -> Result < ( ) > {
477527 self . skip_var_32 ( )
478528 }
479529
530+ /// Advances the `BinaryReader` `len` bytes, skipping the result.
531+ /// # Errors
532+ /// If `BinaryReader` has less than `len` bytes remaining.
480533 pub fn skip_bytes ( & mut self , len : usize ) -> Result < ( ) > {
481534 self . ensure_has_bytes ( len) ?;
482535 self . position += len;
483536 Ok ( ( ) )
484537 }
485538
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`.
486545 pub fn skip_string ( & mut self ) -> Result < ( ) > {
487546 let len = self . read_var_u32 ( ) ? as usize ;
488547 if len > MAX_WASM_STRING_SIZE {
@@ -502,6 +561,11 @@ impl<'a> BinaryReader<'a> {
502561 self . position = position;
503562 }
504563
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.
505569 pub fn read_var_i32 ( & mut self ) -> Result < i32 > {
506570 // Optimization for single byte i32.
507571 let byte = self . read_u8 ( ) ?;
@@ -534,6 +598,11 @@ impl<'a> BinaryReader<'a> {
534598 Ok ( ( result << ashift) >> ashift)
535599 }
536600
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.
537606 pub fn read_var_s33 ( & mut self ) -> Result < i64 > {
538607 // Optimization for single byte.
539608 let byte = self . read_u8 ( ) ?;
@@ -551,7 +620,7 @@ impl<'a> BinaryReader<'a> {
551620 let sign_and_unused_bit = ( byte << 1 ) as i8 >> ( 33 - shift) ;
552621 if continuation_bit || ( sign_and_unused_bit != 0 && sign_and_unused_bit != -1 ) {
553622 return Err ( BinaryReaderError {
554- message : "Invalid var_i33 " ,
623+ message : "Invalid var_s33 " ,
555624 offset : self . original_position ( ) - 1 ,
556625 } ) ;
557626 }
@@ -566,6 +635,11 @@ impl<'a> BinaryReader<'a> {
566635 Ok ( ( result << ashift) >> ashift)
567636 }
568637
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.
569643 pub fn read_var_i64 ( & mut self ) -> Result < i64 > {
570644 let mut result: i64 = 0 ;
571645 let mut shift = 0 ;
@@ -592,16 +666,31 @@ impl<'a> BinaryReader<'a> {
592666 Ok ( ( result << ashift) >> ashift)
593667 }
594668
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.
595674 pub fn read_f32 ( & mut self ) -> Result < Ieee32 > {
596675 let value = self . read_u32 ( ) ?;
597676 Ok ( Ieee32 ( value) )
598677 }
599678
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.
600684 pub fn read_f64 ( & mut self ) -> Result < Ieee64 > {
601685 let value = self . read_u64 ( ) ?;
602686 Ok ( Ieee64 ( value) )
603687 }
604688
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.
605694 pub fn read_string ( & mut self ) -> Result < & ' a str > {
606695 let len = self . read_var_u32 ( ) ? as usize ;
607696 if len > MAX_WASM_STRING_SIZE {
@@ -859,6 +948,10 @@ impl<'a> BinaryReader<'a> {
859948 }
860949 }
861950
951+ /// Reads the next available `Operator`.
952+ /// # Errors
953+ /// If `BinaryReader` has less bytes remaining than required to parse
954+ /// the `Operator`.
862955 pub fn read_operator ( & mut self ) -> Result < Operator < ' a > > {
863956 let code = self . read_u8 ( ) ? as u8 ;
864957 Ok ( match code {
@@ -1442,8 +1535,8 @@ impl<'a> BinaryReader<'a> {
14421535 0xc0 => Operator :: V8x16Swizzle ,
14431536 0x03 | 0xc1 => {
14441537 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 ) ?
14471540 }
14481541 Operator :: V8x16Shuffle { lanes }
14491542 }
@@ -1469,7 +1562,7 @@ impl<'a> BinaryReader<'a> {
14691562 }
14701563
14711564 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 ) ?;
14731566 if magic_number != WASM_MAGIC_NUMBER {
14741567 return Err ( BinaryReaderError {
14751568 message : "Bad magic number" ,
@@ -1560,6 +1653,11 @@ impl<'a> BrTable<'a> {
15601653 self . cnt
15611654 }
15621655
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+
15631661 /// Reads br_table entries.
15641662 ///
15651663 /// # Examples
@@ -1602,6 +1700,7 @@ impl<'a> BrTable<'a> {
16021700/// }
16031701/// }
16041702/// ```
1703+ #[ derive( Clone , Debug ) ]
16051704pub struct BrTableIterator < ' a > {
16061705 reader : BinaryReader < ' a > ,
16071706}
0 commit comments