golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/trace/internal/raw/writer.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  	"encoding/binary"
    13  	"fmt"
    14  	"io"
    15  
    16  	"golang.org/x/exp/trace/internal/event"
    17  	"golang.org/x/exp/trace/internal/version"
    18  )
    19  
    20  // Writer emits the wire format of a trace.
    21  //
    22  // It may not produce a byte-for-byte compatible trace from what is
    23  // produced by the runtime, because it may be missing extra padding
    24  // in the LEB128 encoding that the runtime adds but isn't necessary
    25  // when you know the data up-front.
    26  type Writer struct {
    27  	w     io.Writer
    28  	buf   []byte
    29  	v     version.Version
    30  	specs []event.Spec
    31  }
    32  
    33  // NewWriter creates a new byte format writer.
    34  func NewWriter(w io.Writer, v version.Version) (*Writer, error) {
    35  	_, err := version.WriteHeader(w, v)
    36  	return &Writer{w: w, v: v, specs: v.Specs()}, err
    37  }
    38  
    39  // WriteEvent writes a single event to the trace wire format stream.
    40  func (w *Writer) WriteEvent(e Event) error {
    41  	// Check version.
    42  	if e.Version != w.v {
    43  		return fmt.Errorf("mismatched version between writer (go 1.%d) and event (go 1.%d)", w.v, e.Version)
    44  	}
    45  
    46  	// Write event header byte.
    47  	w.buf = append(w.buf, uint8(e.Ev))
    48  
    49  	// Write out all arguments.
    50  	spec := w.specs[e.Ev]
    51  	for _, arg := range e.Args[:len(spec.Args)] {
    52  		w.buf = binary.AppendUvarint(w.buf, arg)
    53  	}
    54  	if spec.IsStack {
    55  		frameArgs := e.Args[len(spec.Args):]
    56  		for i := 0; i < len(frameArgs); i++ {
    57  			w.buf = binary.AppendUvarint(w.buf, frameArgs[i])
    58  		}
    59  	}
    60  
    61  	// Write out the length of the data.
    62  	if spec.HasData {
    63  		w.buf = binary.AppendUvarint(w.buf, uint64(len(e.Data)))
    64  	}
    65  
    66  	// Write out varint events.
    67  	_, err := w.w.Write(w.buf)
    68  	w.buf = w.buf[:0]
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	// Write out data.
    74  	if spec.HasData {
    75  		_, err := w.w.Write(e.Data)
    76  		return err
    77  	}
    78  	return nil
    79  }