// 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 encodemeta

import (
	
	
	
	
	
	
	
	
	
)

// This package contains APIs and helpers for writing out a meta-data
// file (composed of a file header, offsets/lengths, and then a series of
// meta-data blobs emitted by the compiler, one per Go package).

type CoverageMetaFileWriter struct {
	stab   stringtab.Writer
	mfname string
	w      *bufio.Writer
	tmp    []byte
	debug  bool
}

func ( string,  io.Writer) *CoverageMetaFileWriter {
	 := &CoverageMetaFileWriter{
		mfname: ,
		w:      bufio.NewWriter(),
		tmp:    make([]byte, 64),
	}
	.stab.InitWriter()
	.stab.Lookup("")
	return 
}

func ( *CoverageMetaFileWriter) ( [16]byte,  [][]byte,  coverage.CounterMode,  coverage.CounterGranularity) error {
	 := uint64(unsafe.Sizeof(coverage.MetaFileHeader{}))
	 := .stab.Size()
	 :=  + uint64(16*len())
	 :=  + uint64()

	if .debug {
		fmt.Fprintf(os.Stderr, "=+= sizeof(MetaFileHeader)=%d\n", )
		fmt.Fprintf(os.Stderr, "=+= preambleLength=%d stSize=%d\n", , )
	}

	// Compute total size
	 := 
	for  := 0;  < len(); ++ {
		 += uint64(len([]))
	}

	// Emit header
	 := coverage.MetaFileHeader{
		Magic:        coverage.CovMetaMagic,
		Version:      coverage.MetaFileVersion,
		TotalLength:  ,
		Entries:      uint64(len()),
		MetaFileHash: ,
		StrTabOffset: uint32(),
		StrTabLength: ,
		CMode:        ,
		CGranularity: ,
	}
	var  error
	if  = binary.Write(.w, binary.LittleEndian, );  != nil {
		return fmt.Errorf("error writing %s: %v", .mfname, )
	}

	if .debug {
		fmt.Fprintf(os.Stderr, "=+= len(blobs) is %d\n", .Entries)
	}

	// Emit package offsets section followed by package lengths section.
	 := 
	 := 
	 := make([]byte, 8)
	for ,  := range  {
		binary.LittleEndian.PutUint64(, )
		if _,  = .w.Write();  != nil {
			return fmt.Errorf("error writing %s: %v", .mfname, )
		}
		if .debug {
			fmt.Fprintf(os.Stderr, "=+= pkg offset %d 0x%x\n", , )
		}
		 += uint64(len())
		 += 8
	}
	for ,  := range  {
		 := uint64(len())
		binary.LittleEndian.PutUint64(, )
		if _,  = .w.Write();  != nil {
			return fmt.Errorf("error writing %s: %v", .mfname, )
		}
		if .debug {
			fmt.Fprintf(os.Stderr, "=+= pkg len %d 0x%x\n", , )
		}
		 += 8
	}

	// Emit string table
	if  = .stab.Write(.w);  != nil {
		return 
	}

	// Now emit blobs themselves.
	for ,  := range  {
		if .debug {
			fmt.Fprintf(os.Stderr, "=+= writing blob %d len %d at off=%d hash %s\n", , len(), , fmt.Sprintf("%x", md5.Sum()))
		}
		if _,  = .w.Write();  != nil {
			return fmt.Errorf("error writing %s: %v", .mfname, )
		}
		if .debug {
			fmt.Fprintf(os.Stderr, "=+= wrote package payload of %d bytes\n",
				len())
		}
		 += uint64(len())
	}

	// Flush writer, and we're done.
	if  = .w.Flush();  != nil {
		return fmt.Errorf("error writing %s: %v", .mfname, )
	}
	return nil
}