func readSectionHeader(load loader.L, expectId byte, idError string) (ok bool) { id, err := load.ReadByte() if err != nil { if err == io.EOF { return } panic(err) } if id != expectId { panic(errors.New(idError)) } load.Varuint32() // payload len ok = true return }
func copySection(w io.Writer, r reader.Reader, expectId byte) (ok bool) { store := storer{w} load := loader.L{Reader: r} loop: for { id, err := load.ReadByte() if err != nil { if err == io.EOF { return } panic(err) } switch { case id == sectionids.Unknown: payloadLen := load.Varuint32() if _, err := io.CopyN(ioutil.Discard, load, int64(payloadLen)); err != nil { panic(err) } case id == expectId: store.Byte(id) break loop default: load.UnreadByte() return } } payloadLen := load.Varuint32() store.Varuint32(payloadLen) if _, err := io.CopyN(store, load, int64(payloadLen)); err != nil { panic(err) } ok = true return }
func (m moduleLoader) loadUntil(load loader.L, untilSection byte) byte { var header struct { MagicNumber uint32 Version uint32 } if err := binary.Read(load, binary.LittleEndian, &header); err != nil { panic(err) } if header.MagicNumber != moduleMagicNumber { panic(errors.New("not a WebAssembly module")) } if header.Version != moduleVersion { panic(fmt.Errorf("unsupported module version: %d", header.Version)) } var skipSection func(byte, uint32) error if m.UnknownSectionLoader != nil { skipSection = func(id byte, payloadLen uint32) (err error) { if id == sectionids.Unknown { err = m.UnknownSectionLoader(load, payloadLen) } else { _, err = io.CopyN(ioutil.Discard, load, int64(payloadLen)) } return } } else { skipSection = func(id byte, payloadLen uint32) (err error) { _, err = io.CopyN(ioutil.Discard, load, int64(payloadLen)) return } } var seenId byte for { id, err := load.ReadByte() if err != nil { if err == io.EOF { return 0 } panic(err) } if id != sectionids.Unknown { if id <= seenId { panic(fmt.Errorf("section 0x%x follows section 0x%x", id, seenId)) } seenId = id } if id >= untilSection { load.UnreadByte() return id } payloadLen := load.Varuint32() if f := sectionLoaders[id]; f != nil { f(m, load) } else if err := skipSection(id, payloadLen); err != nil { panic(err) } } }