// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package decodemeta

// This package contains APIs and helpers for decoding a single package's
// meta data "blob" emitted by the compiler when coverage instrumentation
// is turned on.

import (
	
	
	
	
	
	
	
)

// See comments in the encodecovmeta package for details on the format.

type CoverageMetaDataDecoder struct {
	r      *slicereader.Reader
	hdr    coverage.MetaSymbolHeader
	strtab *stringtab.Reader
	tmp    []byte
	debug  bool
}

func ( []byte,  bool) (*CoverageMetaDataDecoder, error) {
	 := slicereader.NewReader(, )
	 := &CoverageMetaDataDecoder{
		r:   ,
		tmp: make([]byte, 0, 256),
	}
	if  := .readHeader();  != nil {
		return nil, 
	}
	if  := .readStringTable();  != nil {
		return nil, 
	}
	return , nil
}

func ( *CoverageMetaDataDecoder) () error {
	if  := binary.Read(.r, binary.LittleEndian, &.hdr);  != nil {
		return 
	}
	if .debug {
		fmt.Fprintf(os.Stderr, "=-= after readHeader: %+v\n", .hdr)
	}
	return nil
}

func ( *CoverageMetaDataDecoder) () error {
	// Seek to the correct location to read the string table.
	 := int64(coverage.CovMetaHeaderSize + 4*.hdr.NumFuncs)
	if ,  := .r.Seek(, io.SeekStart);  != nil {
		return 
	}

	// Read the table itself.
	.strtab = stringtab.NewReader(.r)
	.strtab.Read()
	return nil
}

func ( *CoverageMetaDataDecoder) () string {
	return .strtab.Get(.hdr.PkgPath)
}

func ( *CoverageMetaDataDecoder) () string {
	return .strtab.Get(.hdr.PkgName)
}

func ( *CoverageMetaDataDecoder) () string {
	return .strtab.Get(.hdr.ModulePath)
}

func ( *CoverageMetaDataDecoder) () uint32 {
	return .hdr.NumFuncs
}

// ReadFunc reads the coverage meta-data for the function with index
// 'findex', filling it into the FuncDesc pointed to by 'f'.
func ( *CoverageMetaDataDecoder) ( uint32,  *coverage.FuncDesc) error {
	if  >= .hdr.NumFuncs {
		return fmt.Errorf("illegal function index")
	}

	// Seek to the correct location to read the function offset and read it.
	 := int64(coverage.CovMetaHeaderSize + 4*)
	if ,  := .r.Seek(, io.SeekStart);  != nil {
		return 
	}
	 := .r.ReadUint32()

	// Check assumptions
	if  < uint32() ||  > .hdr.Length {
		return fmt.Errorf("malformed func offset %d", )
	}

	// Seek to the correct location to read the function.
	 := int64()
	if ,  := .r.Seek(, io.SeekStart);  != nil {
		return 
	}

	// Preamble containing number of units, file, and function.
	 := uint32(.r.ReadULEB128())
	 := uint32(.r.ReadULEB128())
	 := uint32(.r.ReadULEB128())

	.Srcfile = .strtab.Get()
	.Funcname = .strtab.Get()

	// Now the units
	.Units = .Units[:0]
	if cap(.Units) < int() {
		.Units = make([]coverage.CoverableUnit, 0, )
	}
	for  := uint32(0);  < ; ++ {
		.Units = append(.Units,
			coverage.CoverableUnit{
				StLine:  uint32(.r.ReadULEB128()),
				StCol:   uint32(.r.ReadULEB128()),
				EnLine:  uint32(.r.ReadULEB128()),
				EnCol:   uint32(.r.ReadULEB128()),
				NxStmts: uint32(.r.ReadULEB128()),
			})
	}
	 := .r.ReadULEB128()
	.Lit =  != 0
	return nil
}