package binary
import (
"bytes"
"fmt"
"io"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/leb128"
"github.com/tetratelabs/wazero/internal/wasm"
)
func decodeTypeSection(enabledFeatures api .CoreFeatures , r *bytes .Reader ) ([]wasm .FunctionType , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get size of vector: %w" , err )
}
result := make ([]wasm .FunctionType , vs )
for i := uint32 (0 ); i < vs ; i ++ {
if err = decodeFunctionType (enabledFeatures , r , &result [i ]); err != nil {
return nil , fmt .Errorf ("read %d-th type: %v" , i , err )
}
}
return result , nil
}
func decodeImportSection(
r *bytes .Reader ,
memorySizer memorySizer ,
memoryLimitPages uint32 ,
enabledFeatures api .CoreFeatures ,
) (result []wasm .Import ,
perModule map [string ][]*wasm .Import ,
funcCount , globalCount , memoryCount , tableCount wasm .Index , err error ,
) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
err = fmt .Errorf ("get size of vector: %w" , err )
return
}
perModule = make (map [string ][]*wasm .Import )
result = make ([]wasm .Import , vs )
for i := uint32 (0 ); i < vs ; i ++ {
imp := &result [i ]
if err = decodeImport (r , i , memorySizer , memoryLimitPages , enabledFeatures , imp ); err != nil {
return
}
switch imp .Type {
case wasm .ExternTypeFunc :
imp .IndexPerType = funcCount
funcCount ++
case wasm .ExternTypeGlobal :
imp .IndexPerType = globalCount
globalCount ++
case wasm .ExternTypeMemory :
imp .IndexPerType = memoryCount
memoryCount ++
case wasm .ExternTypeTable :
imp .IndexPerType = tableCount
tableCount ++
}
perModule [imp .Module ] = append (perModule [imp .Module ], imp )
}
return
}
func decodeFunctionSection(r *bytes .Reader ) ([]uint32 , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get size of vector: %w" , err )
}
result := make ([]uint32 , vs )
for i := uint32 (0 ); i < vs ; i ++ {
if result [i ], _, err = leb128 .DecodeUint32 (r ); err != nil {
return nil , fmt .Errorf ("get type index: %w" , err )
}
}
return result , err
}
func decodeTableSection(r *bytes .Reader , enabledFeatures api .CoreFeatures ) ([]wasm .Table , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("error reading size" )
}
if vs > 1 {
if err := enabledFeatures .RequireEnabled (api .CoreFeatureReferenceTypes ); err != nil {
return nil , fmt .Errorf ("at most one table allowed in module as %w" , err )
}
}
ret := make ([]wasm .Table , vs )
for i := range ret {
err = decodeTable (r , enabledFeatures , &ret [i ])
if err != nil {
return nil , err
}
}
return ret , nil
}
func decodeMemorySection(
r *bytes .Reader ,
enabledFeatures api .CoreFeatures ,
memorySizer memorySizer ,
memoryLimitPages uint32 ,
) (*wasm .Memory , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("error reading size" )
}
if vs > 1 {
return nil , fmt .Errorf ("at most one memory allowed in module, but read %d" , vs )
} else if vs == 0 {
return nil , nil
}
return decodeMemory (r , enabledFeatures , memorySizer , memoryLimitPages )
}
func decodeGlobalSection(r *bytes .Reader , enabledFeatures api .CoreFeatures ) ([]wasm .Global , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get size of vector: %w" , err )
}
result := make ([]wasm .Global , vs )
for i := uint32 (0 ); i < vs ; i ++ {
if err = decodeGlobal (r , enabledFeatures , &result [i ]); err != nil {
return nil , fmt .Errorf ("global[%d]: %w" , i , err )
}
}
return result , nil
}
func decodeExportSection(r *bytes .Reader ) ([]wasm .Export , map [string ]*wasm .Export , error ) {
vs , _ , sizeErr := leb128 .DecodeUint32 (r )
if sizeErr != nil {
return nil , nil , fmt .Errorf ("get size of vector: %v" , sizeErr )
}
exportMap := make (map [string ]*wasm .Export , vs )
exportSection := make ([]wasm .Export , vs )
for i := wasm .Index (0 ); i < vs ; i ++ {
export := &exportSection [i ]
err := decodeExport (r , export )
if err != nil {
return nil , nil , fmt .Errorf ("read export: %w" , err )
}
if _ , ok := exportMap [export .Name ]; ok {
return nil , nil , fmt .Errorf ("export[%d] duplicates name %q" , i , export .Name )
} else {
exportMap [export .Name ] = export
}
}
return exportSection , exportMap , nil
}
func decodeStartSection(r *bytes .Reader ) (*wasm .Index , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get function index: %w" , err )
}
return &vs , nil
}
func decodeElementSection(r *bytes .Reader , enabledFeatures api .CoreFeatures ) ([]wasm .ElementSegment , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get size of vector: %w" , err )
}
result := make ([]wasm .ElementSegment , vs )
for i := uint32 (0 ); i < vs ; i ++ {
if err = decodeElementSegment (r , enabledFeatures , &result [i ]); err != nil {
return nil , fmt .Errorf ("read element: %w" , err )
}
}
return result , nil
}
func decodeCodeSection(r *bytes .Reader ) ([]wasm .Code , error ) {
codeSectionStart := uint64 (r .Len ())
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get size of vector: %w" , err )
}
result := make ([]wasm .Code , vs )
for i := uint32 (0 ); i < vs ; i ++ {
err = decodeCode (r , codeSectionStart , &result [i ])
if err != nil {
return nil , fmt .Errorf ("read %d-th code segment: %v" , i , err )
}
}
return result , nil
}
func decodeDataSection(r *bytes .Reader , enabledFeatures api .CoreFeatures ) ([]wasm .DataSegment , error ) {
vs , _ , err := leb128 .DecodeUint32 (r )
if err != nil {
return nil , fmt .Errorf ("get size of vector: %w" , err )
}
result := make ([]wasm .DataSegment , vs )
for i := uint32 (0 ); i < vs ; i ++ {
if err = decodeDataSegment (r , enabledFeatures , &result [i ]); err != nil {
return nil , fmt .Errorf ("read data segment: %w" , err )
}
}
return result , nil
}
func decodeDataCountSection(r *bytes .Reader ) (count *uint32 , err error ) {
v , _ , err := leb128 .DecodeUint32 (r )
if err != nil && err != io .EOF {
return nil , err
}
return &v , nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .