golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/trace/internal/raw/reader.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT.
     6  
     7  //go:build go1.21
     8  
     9  package raw
    10  
    11  import (
    12  	"bufio"
    13  	"encoding/binary"
    14  	"fmt"
    15  	"io"
    16  
    17  	"golang.org/x/exp/trace/internal/event"
    18  	"golang.org/x/exp/trace/internal/version"
    19  )
    20  
    21  // Reader parses trace bytes with only very basic validation
    22  // into an event stream.
    23  type Reader struct {
    24  	r     *bufio.Reader
    25  	v     version.Version
    26  	specs []event.Spec
    27  }
    28  
    29  // NewReader creates a new reader for the trace wire format.
    30  func NewReader(r io.Reader) (*Reader, error) {
    31  	br := bufio.NewReader(r)
    32  	v, err := version.ReadHeader(br)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	return &Reader{r: br, v: v, specs: v.Specs()}, nil
    37  }
    38  
    39  // Version returns the version of the trace that we're reading.
    40  func (r *Reader) Version() version.Version {
    41  	return r.v
    42  }
    43  
    44  // ReadEvent reads and returns the next trace event in the byte stream.
    45  func (r *Reader) ReadEvent() (Event, error) {
    46  	evb, err := r.r.ReadByte()
    47  	if err == io.EOF {
    48  		return Event{}, io.EOF
    49  	}
    50  	if err != nil {
    51  		return Event{}, err
    52  	}
    53  	if int(evb) >= len(r.specs) || evb == 0 {
    54  		return Event{}, fmt.Errorf("invalid event type: %d", evb)
    55  	}
    56  	ev := event.Type(evb)
    57  	spec := r.specs[ev]
    58  	args, err := r.readArgs(len(spec.Args))
    59  	if err != nil {
    60  		return Event{}, err
    61  	}
    62  	if spec.IsStack {
    63  		len := int(args[1])
    64  		for i := 0; i < len; i++ {
    65  			// Each stack frame has four args: pc, func ID, file ID, line number.
    66  			frame, err := r.readArgs(4)
    67  			if err != nil {
    68  				return Event{}, err
    69  			}
    70  			args = append(args, frame...)
    71  		}
    72  	}
    73  	var data []byte
    74  	if spec.HasData {
    75  		data, err = r.readData()
    76  		if err != nil {
    77  			return Event{}, err
    78  		}
    79  	}
    80  	return Event{
    81  		Version: r.v,
    82  		Ev:      ev,
    83  		Args:    args,
    84  		Data:    data,
    85  	}, nil
    86  }
    87  
    88  func (r *Reader) readArgs(n int) ([]uint64, error) {
    89  	var args []uint64
    90  	for i := 0; i < n; i++ {
    91  		val, err := binary.ReadUvarint(r.r)
    92  		if err != nil {
    93  			return nil, err
    94  		}
    95  		args = append(args, val)
    96  	}
    97  	return args, nil
    98  }
    99  
   100  func (r *Reader) readData() ([]byte, error) {
   101  	len, err := binary.ReadUvarint(r.r)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	var data []byte
   106  	for i := 0; i < int(len); i++ {
   107  		b, err := r.r.ReadByte()
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		data = append(data, b)
   112  	}
   113  	return data, nil
   114  }