github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/iofmt/prefixwriter.go (about)

     1  // Copyright 2018 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package iofmt contains various IO utilities used for formatting
     6  // output.
     7  package iofmt
     8  
     9  import (
    10  	"bytes"
    11  	"io"
    12  )
    13  
    14  var newline = []byte{'\n'}
    15  
    16  // prefixWriter is an io.Writer that outputs a prefix before each line.
    17  type prefixWriter struct {
    18  	w          io.Writer
    19  	prefix     string
    20  	needPrefix bool
    21  }
    22  
    23  // PrefixWriter returns a new io.Writer that copies its writes
    24  // to the provided io.Writer, adding a prefix at the beginning
    25  // of each line.
    26  func PrefixWriter(w io.Writer, prefix string) io.Writer {
    27  	return &prefixWriter{w: w, prefix: prefix, needPrefix: true}
    28  }
    29  
    30  func (w *prefixWriter) Write(p []byte) (n int, err error) {
    31  	if w.needPrefix {
    32  		if _, err := io.WriteString(w.w, w.prefix); err != nil {
    33  			return 0, err
    34  		}
    35  		w.needPrefix = false
    36  	}
    37  	for {
    38  		i := bytes.Index(p, newline)
    39  		switch i {
    40  		case len(p) - 1:
    41  			w.needPrefix = true
    42  			fallthrough
    43  		case -1:
    44  			m, err := w.w.Write(p)
    45  			return n + m, err
    46  		default:
    47  			m, err := w.w.Write(p[:i+1])
    48  			n += m
    49  			if err != nil {
    50  				return n, err
    51  			}
    52  			_, err = io.WriteString(w.w, w.prefix)
    53  			if err != nil {
    54  				return n, err
    55  			}
    56  			p = p[i+1:]
    57  		}
    58  	}
    59  }