// Copyright 2023 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 trace

import (
	
	
	
	

	
	
)

// timestamp is an unprocessed timestamp.
type timestamp uint64

// batch represents a batch of trace events.
// It is unparsed except for its header.
type batch struct {
	m    ThreadID
	time timestamp
	data []byte
	exp  event.Experiment
}

func ( *batch) () bool {
	return .exp == event.NoExperiment && len(.data) > 0 && event.Type(.data[0]) == go122.EvStrings
}

func ( *batch) () bool {
	return .exp == event.NoExperiment && len(.data) > 0 && event.Type(.data[0]) == go122.EvStacks
}

func ( *batch) () bool {
	return .exp == event.NoExperiment && len(.data) > 0 && event.Type(.data[0]) == go122.EvCPUSamples
}

func ( *batch) () bool {
	return .exp == event.NoExperiment && len(.data) > 0 && event.Type(.data[0]) == go122.EvFrequency
}

// readBatch reads the next full batch from r.
func readBatch( interface {
	io.Reader
	io.ByteReader
}) (batch, uint64, error) {
	// Read batch header byte.
	,  := .ReadByte()
	if  != nil {
		return batch{}, 0, 
	}
	if  := event.Type();  != go122.EvEventBatch &&  != go122.EvExperimentalBatch {
		return batch{}, 0, fmt.Errorf("expected batch event, got %s", go122.EventString())
	}

	// Read the experiment of we have one.
	 := event.NoExperiment
	if event.Type() == go122.EvExperimentalBatch {
		,  := .ReadByte()
		if  != nil {
			return batch{}, 0, 
		}
		 = event.Experiment()
	}

	// Read the batch header: gen (generation), thread (M) ID, base timestamp
	// for the batch.
	,  := binary.ReadUvarint()
	if  != nil {
		return batch{}, , fmt.Errorf("error reading batch gen: %w", )
	}
	,  := binary.ReadUvarint()
	if  != nil {
		return batch{}, , fmt.Errorf("error reading batch M ID: %w", )
	}
	,  := binary.ReadUvarint()
	if  != nil {
		return batch{}, , fmt.Errorf("error reading batch timestamp: %w", )
	}

	// Read in the size of the batch to follow.
	,  := binary.ReadUvarint()
	if  != nil {
		return batch{}, , fmt.Errorf("error reading batch size: %w", )
	}
	if  > go122.MaxBatchSize {
		return batch{}, , fmt.Errorf("invalid batch size %d, maximum is %d", , go122.MaxBatchSize)
	}

	// Copy out the batch for later processing.
	var  bytes.Buffer
	.Grow(int())
	,  := io.CopyN(&, , int64())
	if  != int64() {
		return batch{}, , fmt.Errorf("failed to read full batch: read %d but wanted %d", , )
	}
	if  != nil {
		return batch{}, , fmt.Errorf("copying batch data: %w", )
	}

	// Return the batch.
	return batch{
		m:    ThreadID(),
		time: timestamp(),
		data: .Bytes(),
		exp:  ,
	}, , nil
}