github.com/cockroachdb/errors@v1.11.1/errbase/format_error.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied. See the License for the specific language governing
    13  // permissions and limitations under the License.
    14  
    15  // This file is forked and modified from golang.org/x/xerrors,
    16  // at commit 3ee3066db522c6628d440a3a91c4abdd7f5ef22f (2019-05-10).
    17  // From the original code:
    18  // Copyright 2018 The Go Authors. All rights reserved.
    19  // Use of this source code is governed by a BSD-style
    20  // license that can be found in the LICENSE file.
    21  //
    22  // Changes specific to this fork marked as inline comments.
    23  
    24  package errbase
    25  
    26  import (
    27  	"bytes"
    28  	"fmt"
    29  	"io"
    30  	"reflect"
    31  	"strings"
    32  
    33  	"github.com/cockroachdb/redact"
    34  	"github.com/kr/pretty"
    35  	pkgErr "github.com/pkg/errors"
    36  )
    37  
    38  // FormatError formats an error according to s and verb.
    39  // This is a helper meant for use when implementing the fmt.Formatter
    40  // interface on custom error objects.
    41  //
    42  // If the error implements errors.Formatter, FormatError calls its
    43  // FormatError method of f with an errors.Printer configured according
    44  // to s and verb, and writes the result to s.
    45  //
    46  // Otherwise, if it is a wrapper, FormatError prints out its error prefix,
    47  // then recurses on its cause.
    48  //
    49  // Otherwise, its Error() text is printed.
    50  func FormatError(err error, s fmt.State, verb rune) {
    51  	formatErrorInternal(err, s, verb, false /* redactableOutput */)
    52  }
    53  
    54  // FormatRedactableError formats an error as a safe object.
    55  //
    56  // Note that certain verb/flags combinations are currently not
    57  // supported, and result in a rendering that considers the entire
    58  // object as unsafe. For example, %q, %#v are not yet supported.
    59  func FormatRedactableError(err error, s redact.SafePrinter, verb rune) {
    60  	formatErrorInternal(err, s, verb, true /* redactable */)
    61  }
    62  
    63  func init() {
    64  	// Also inform the redact package of how to print an error
    65  	// safely. This is used when an error is passed as argument
    66  	// to one of the redact print functions.
    67  	redact.RegisterRedactErrorFn(FormatRedactableError)
    68  }
    69  
    70  // Formattable wraps an error into a fmt.Formatter which
    71  // will provide "smart" formatting even if the outer layer
    72  // of the error does not implement the Formatter interface.
    73  func Formattable(err error) fmt.Formatter {
    74  	return &errorFormatter{err}
    75  }
    76  
    77  // formatErrorInternal is the shared logic between FormatError
    78  // and FormatErrorRedactable.
    79  //
    80  // When the redactableOutput argument is true, the fmt.State argument
    81  // is really a redact.SafePrinter and casted down as necessary.
    82  //
    83  // If verb and flags are not one of the supported error formatting
    84  // combinations (in particular, %q, %#v etc), then the redactableOutput
    85  // argument is ignored. This limitation may be lifted in a later
    86  // version.
    87  func formatErrorInternal(err error, s fmt.State, verb rune, redactableOutput bool) {
    88  	// Assuming this function is only called from the Format method, and given
    89  	// that FormatError takes precedence over Format, it cannot be called from
    90  	// any package that supports errors.Formatter. It is therefore safe to
    91  	// disregard that State may be a specific printer implementation and use one
    92  	// of our choice instead.
    93  
    94  	p := state{State: s, redactableOutput: redactableOutput}
    95  
    96  	switch {
    97  	case verb == 'v' && s.Flag('+') && !s.Flag('#'):
    98  		// Here we are going to format as per %+v, into p.buf.
    99  		//
   100  		// We need to start with the innermost (root cause) error first,
   101  		// then the layers of wrapping from innermost to outermost, so as
   102  		// to enable stack trace de-duplication. This requires a
   103  		// post-order traversal. Since we have a linked list, the best we
   104  		// can do is a recursion.
   105  		p.formatRecursive(
   106  			err,
   107  			true,  /* isOutermost */
   108  			true,  /* withDetail */
   109  			false, /* withDepth */
   110  			0,     /* depth */
   111  		)
   112  
   113  		// We now have all the data, we can render the result.
   114  		p.formatEntries(err)
   115  
   116  		// We're done formatting. Apply width/precision parameters.
   117  		p.finishDisplay(verb)
   118  
   119  	case !redactableOutput && verb == 'v' && s.Flag('#'):
   120  		// We only know how to process %#v if redactable output is not
   121  		// requested. This is because the structured output may emit
   122  		// arbitrary unsafe strings without redaction markers,
   123  		// or improperly balanced/escaped redaction markers.
   124  		if stringer, ok := err.(fmt.GoStringer); ok {
   125  			io.WriteString(&p.finalBuf, stringer.GoString())
   126  		} else {
   127  			// Not a GoStringer: delegate to the pretty library.
   128  			fmt.Fprintf(&p.finalBuf, "%# v", pretty.Formatter(err))
   129  		}
   130  		p.finishDisplay(verb)
   131  
   132  	case verb == 's' ||
   133  		// We only handle %v/%+v or other combinations here; %#v is unsupported.
   134  		(verb == 'v' && !s.Flag('#')) ||
   135  		// If redactable output is not requested, then we also
   136  		// know how to format %x/%X (print bytes of error message in hex)
   137  		// and %q (quote the result).
   138  		// If redactable output is requested, then we don't know
   139  		// how to perform these exotic verbs, because they
   140  		// may muck with the redaction markers. In this case,
   141  		// we simply refuse the format as per the default clause below.
   142  		(!redactableOutput && (verb == 'x' || verb == 'X' || verb == 'q')):
   143  		// Only the error message.
   144  		//
   145  		// Use an intermediate buffer because there may be alignment
   146  		// instructions to obey in the final rendering or
   147  		// quotes to add (for %q).
   148  		//
   149  		// Conceptually, we could just do
   150  		//       p.buf.WriteString(err.Error())
   151  		// However we also advertise that Error() can be implemented
   152  		// by calling FormatError(), in which case we'd get an infinite
   153  		// recursion. So we have no choice but to peel the data
   154  		// and then assemble the pieces ourselves.
   155  		p.formatRecursive(
   156  			err,
   157  			true,  /* isOutermost */
   158  			false, /* withDetail */
   159  			false, /* withDepth */
   160  			0,     /* depth */
   161  		)
   162  		p.formatSingleLineOutput()
   163  		p.finishDisplay(verb)
   164  
   165  	default:
   166  		// Unknown verb. Do like fmt.Printf and tell the user we're
   167  		// confused.
   168  		//
   169  		// Note that the following logic is correct regardless of the
   170  		// value of 'redactableOutput', because the display of the verb and type
   171  		// are always safe for redaction. If/when this code is changed to
   172  		// print more details, care is to be taken to add redaction
   173  		// markers if s.redactableOutput is set.
   174  		p.finalBuf.WriteString("%!")
   175  		p.finalBuf.WriteRune(verb)
   176  		p.finalBuf.WriteByte('(')
   177  		switch {
   178  		case err != nil:
   179  			p.finalBuf.WriteString(reflect.TypeOf(err).String())
   180  		default:
   181  			p.finalBuf.WriteString("<nil>")
   182  		}
   183  		p.finalBuf.WriteByte(')')
   184  		io.Copy(s, &p.finalBuf)
   185  	}
   186  }
   187  
   188  // formatEntries reads the entries from s.entries and produces a
   189  // detailed rendering in s.finalBuf.
   190  //
   191  // Note that if s.redactableOutput is true, s.finalBuf is to contain a
   192  // RedactableBytes. However, we are not using the helper facilities
   193  // from redact.SafePrinter to do this, so care should be taken below
   194  // to properly escape markers, etc.
   195  func (s *state) formatEntries(err error) {
   196  	// The first entry at the top is special. We format it as follows:
   197  	//
   198  	//   <complete error message>
   199  	//   (1) <details>
   200  	s.formatSingleLineOutput()
   201  	s.finalBuf.WriteString("\n(1)")
   202  
   203  	s.printEntry(s.entries[len(s.entries)-1])
   204  
   205  	// All the entries that follow are printed as follows:
   206  	//
   207  	// Wraps: (N) <details>
   208  	//
   209  	for i, j := len(s.entries)-2, 2; i >= 0; i, j = i-1, j+1 {
   210  		s.finalBuf.WriteByte('\n')
   211  		// Extra indentation starts at depth==2 because the direct
   212  		// children of the root error area already printed on separate
   213  		// newlines.
   214  		for m := 0; m < s.entries[i].depth-1; m += 1 {
   215  			if m == s.entries[i].depth-2 {
   216  				s.finalBuf.WriteString("└─ ")
   217  			} else {
   218  				s.finalBuf.WriteByte(' ')
   219  				s.finalBuf.WriteByte(' ')
   220  			}
   221  		}
   222  		fmt.Fprintf(&s.finalBuf, "Wraps: (%d)", j)
   223  		entry := s.entries[i]
   224  		s.printEntry(entry)
   225  	}
   226  
   227  	// At the end, we link all the (N) references to the Go type of the
   228  	// error.
   229  	s.finalBuf.WriteString("\nError types:")
   230  	for i, j := len(s.entries)-1, 1; i >= 0; i, j = i-1, j+1 {
   231  		fmt.Fprintf(&s.finalBuf, " (%d) %T", j, s.entries[i].err)
   232  	}
   233  }
   234  
   235  // printEntry renders the entry given as argument
   236  // into s.finalBuf.
   237  //
   238  // If s.redactableOutput is set, then s.finalBuf is to contain
   239  // a RedactableBytes, with redaction markers. In that
   240  // case, we must be careful to escape (or not) the entry
   241  // depending on entry.redactable.
   242  //
   243  // If s.redactableOutput is unset, then we are not caring about
   244  // redactability. In that case entry.redactable is not set
   245  // anyway and we can pass contents through.
   246  func (s *state) printEntry(entry formatEntry) {
   247  	if len(entry.head) > 0 {
   248  		if entry.head[0] != '\n' {
   249  			s.finalBuf.WriteByte(' ')
   250  		}
   251  		if len(entry.head) > 0 {
   252  			if !s.redactableOutput || entry.redactable {
   253  				// If we don't care about redaction, then we can pass the string
   254  				// through.
   255  				//
   256  				// If we do care about redaction, and entry.redactable is true,
   257  				// then entry.head is already a RedactableBytes. Then we can
   258  				// also pass it through.
   259  				s.finalBuf.Write(entry.head)
   260  			} else {
   261  				// We care about redaction, and the head is unsafe. Escape it
   262  				// and enclose the result within redaction markers.
   263  				s.finalBuf.Write([]byte(redact.EscapeBytes(entry.head)))
   264  			}
   265  		}
   266  	}
   267  	if len(entry.details) > 0 {
   268  		if len(entry.head) == 0 {
   269  			if entry.details[0] != '\n' {
   270  				s.finalBuf.WriteByte(' ')
   271  			}
   272  		}
   273  		if !s.redactableOutput || entry.redactable {
   274  			// If we don't care about redaction, then we can pass the string
   275  			// through.
   276  			//
   277  			// If we do care about redaction, and entry.redactable is true,
   278  			// then entry.details is already a RedactableBytes. Then we can
   279  			// also pass it through.
   280  			s.finalBuf.Write(entry.details)
   281  		} else {
   282  			// We care about redaction, and the details are unsafe. Escape
   283  			// them and enclose the result within redaction markers.
   284  			s.finalBuf.Write([]byte(redact.EscapeBytes(entry.details)))
   285  		}
   286  	}
   287  	if entry.stackTrace != nil {
   288  		s.finalBuf.WriteString("\n  -- stack trace:")
   289  		s.finalBuf.WriteString(strings.ReplaceAll(
   290  			fmt.Sprintf("%+v", entry.stackTrace),
   291  			"\n", string(detailSep)))
   292  		if entry.elidedStackTrace {
   293  			fmt.Fprintf(&s.finalBuf, "%s[...repeated from below...]", detailSep)
   294  		}
   295  	}
   296  }
   297  
   298  // formatSingleLineOutput prints the details extracted via
   299  // formatRecursive() through the chain of errors as if .Error() has
   300  // been called: it only prints the non-detail parts and prints them on
   301  // one line with ": " separators.
   302  //
   303  // This function is used both when FormatError() is called indirectly
   304  // from .Error(), e.g. in:
   305  //
   306  //	(e *myType) Error() { return fmt.Sprintf("%v", e) }
   307  //	(e *myType) Format(s fmt.State, verb rune) { errors.FormatError(s, verb, e) }
   308  //
   309  // and also to print the first line in the output of a %+v format.
   310  //
   311  // It reads from s.entries and writes to s.finalBuf.
   312  // s.buf is left untouched.
   313  //
   314  // Note that if s.redactableOutput is true, s.finalBuf is to contain a
   315  // RedactableBytes. However, we are not using the helper facilities
   316  // from redact.SafePrinter to do this, so care should be taken below
   317  // to properly escape markers, etc.
   318  func (s *state) formatSingleLineOutput() {
   319  	for i := len(s.entries) - 1; i >= 0; i-- {
   320  		entry := &s.entries[i]
   321  		if entry.elideShort {
   322  			continue
   323  		}
   324  		if s.finalBuf.Len() > 0 && len(entry.head) > 0 {
   325  			s.finalBuf.WriteString(": ")
   326  		}
   327  		if len(entry.head) == 0 {
   328  			// shortcut, to avoid the copy below.
   329  			continue
   330  		}
   331  		if !s.redactableOutput || entry.redactable {
   332  			// If we don't care about redaction, then we can pass the string
   333  			// through.
   334  			//
   335  			// If we do care about redaction, and entry.redactable is true,
   336  			// then entry.head is already a RedactableBytes. Then we can
   337  			// also pass it through.
   338  			s.finalBuf.Write(entry.head)
   339  		} else {
   340  			// We do care about redaction, but entry.redactable is unset.
   341  			// This means entry.head is unsafe. We need to escape it.
   342  			s.finalBuf.Write([]byte(redact.EscapeBytes(entry.head)))
   343  		}
   344  	}
   345  }
   346  
   347  // formatRecursive performs a post-order traversal on the chain of
   348  // errors to collect error details from innermost to outermost.
   349  //
   350  // It uses s.buf as an intermediate buffer to collect strings.
   351  // It populates s.entries as a result.
   352  // Between each layer of error, s.buf is reset.
   353  //
   354  // s.finalBuf is untouched. The conversion of s.entries
   355  // to s.finalBuf is done by formatSingleLineOutput() and/or
   356  // formatEntries().
   357  //
   358  // `withDepth` and `depth` are used to tag subtrees of multi-cause
   359  // errors for added indentation during printing. Once a multi-cause
   360  // error is encountered, all subsequent calls with set `withDepth` to
   361  // true, and increment `depth` during recursion. This information is
   362  // persisted into the generated entries and used later to display the
   363  // error with increased indentation based in the depth.
   364  func (s *state) formatRecursive(err error, isOutermost, withDetail, withDepth bool, depth int) int {
   365  	cause := UnwrapOnce(err)
   366  	numChildren := 0
   367  	if cause != nil {
   368  		// Recurse first, which populates entries list starting from innermost
   369  		// entry. If we've previously seen a multi-cause wrapper, `withDepth`
   370  		// will be true, and we'll record the depth below ensuring that extra
   371  		// indentation is applied to this inner cause during printing.
   372  		// Otherwise, we maintain "straight" vertical formatting by keeping the
   373  		// parent callers `withDepth` value of `false` by default.
   374  		numChildren += s.formatRecursive(cause, false, withDetail, withDepth, depth+1)
   375  	}
   376  
   377  	causes := UnwrapMulti(err)
   378  	for _, c := range causes {
   379  		// Override `withDepth` to true for all child entries ensuring they have
   380  		// indentation applied during formatting to distinguish them from
   381  		// parents.
   382  		numChildren += s.formatRecursive(c, false, withDetail, true, depth+1)
   383  	}
   384  	// inserted := len(s.entries) - 1 - startChildren
   385  
   386  	// Reinitialize the state for this stage of wrapping.
   387  	s.wantDetail = withDetail
   388  	s.needSpace = false
   389  	s.needNewline = 0
   390  	s.multiLine = false
   391  	s.notEmpty = false
   392  	s.hasDetail = false
   393  	s.headBuf = nil
   394  
   395  	seenTrace := false
   396  
   397  	bufIsRedactable := false
   398  
   399  	switch v := err.(type) {
   400  	case SafeFormatter:
   401  		bufIsRedactable = true
   402  		desiredShortening := v.SafeFormatError((*safePrinter)(s))
   403  		if desiredShortening == nil {
   404  			// The error wants to elide the short messages from inner causes.
   405  			// Read backwards through list of entries up to the number of new
   406  			// entries created "under" this one amount and mark `elideShort`
   407  			// true.
   408  			s.elideShortChildren(numChildren)
   409  		}
   410  
   411  	case Formatter:
   412  		desiredShortening := v.FormatError((*printer)(s))
   413  		if desiredShortening == nil {
   414  			// The error wants to elide the short messages from inner
   415  			// causes. Do it.
   416  			s.elideShortChildren(numChildren)
   417  		}
   418  
   419  	case fmt.Formatter:
   420  		// We can only use a fmt.Formatter when both the following
   421  		// conditions are true:
   422  		// - when it is the leaf error, because a fmt.Formatter
   423  		//   on a wrapper also recurses.
   424  		// - when it is not the outermost wrapper, because
   425  		//   the Format() method is likely to be calling FormatError()
   426  		//   to do its job and we want to avoid an infinite recursion.
   427  		if !isOutermost && cause == nil {
   428  			v.Format(s, 'v')
   429  			if st, ok := err.(StackTraceProvider); ok {
   430  				// This is likely a leaf error from github/pkg/errors.
   431  				// The thing probably printed its stack trace on its own.
   432  				seenTrace = true
   433  				// We'll subsequently simplify stack traces in wrappers.
   434  				s.lastStack = st.StackTrace()
   435  			}
   436  		} else {
   437  			if elideCauseMsg := s.formatSimple(err, cause); elideCauseMsg {
   438  				// The error wants to elide the short messages from inner
   439  				// causes. Do it.
   440  				s.elideShortChildren(numChildren)
   441  			}
   442  		}
   443  
   444  	default:
   445  		// Handle the special case overrides for context.Canceled,
   446  		// os.PathError, etc for which we know how to extract some safe
   447  		// strings.
   448  		//
   449  		// We need to do this in the `default` branch, instead of doing
   450  		// this above the switch, because the special handler could call a
   451  		// .Error() that delegates its implementation to fmt.Formatter,
   452  		// errors.Safeformatter or errors.Formattable, which brings us
   453  		// back to this method in a call cycle. So we need to handle the
   454  		// various interfaces first.
   455  		printDone := false
   456  		for _, fn := range specialCases {
   457  			if handled, desiredShortening := fn(err, (*safePrinter)(s), cause == nil /* leaf */); handled {
   458  				printDone = true
   459  				bufIsRedactable = true
   460  				if desiredShortening == nil {
   461  					// The error wants to elide the short messages from inner
   462  					// causes. Do it.
   463  					s.elideShortChildren(numChildren)
   464  				}
   465  				break
   466  			}
   467  		}
   468  		if !printDone {
   469  			// If the error did not implement errors.Formatter nor
   470  			// fmt.Formatter, but it is a wrapper, still attempt best effort:
   471  			// print what we can at this level.
   472  			elideChildren := s.formatSimple(err, cause)
   473  			// always elideChildren when dealing with multi-cause errors.
   474  			if len(causes) > 0 {
   475  				elideChildren = true
   476  			}
   477  			if elideChildren {
   478  				// The error wants to elide the short messages from inner
   479  				// causes. Do it.
   480  				s.elideShortChildren(numChildren)
   481  			}
   482  		}
   483  	}
   484  
   485  	// Collect the result.
   486  	entry := s.collectEntry(err, bufIsRedactable, withDepth, depth)
   487  
   488  	// If there's an embedded stack trace, also collect it.
   489  	// This will get either a stack from pkg/errors, or ours.
   490  	if !seenTrace {
   491  		if st, ok := err.(StackTraceProvider); ok {
   492  			entry.stackTrace, entry.elidedStackTrace = ElideSharedStackTraceSuffix(s.lastStack, st.StackTrace())
   493  			s.lastStack = entry.stackTrace
   494  		}
   495  	}
   496  
   497  	// Remember the entry for later rendering.
   498  	s.entries = append(s.entries, entry)
   499  	s.buf = bytes.Buffer{}
   500  
   501  	return numChildren + 1
   502  }
   503  
   504  // elideShortChildren takes a number of entries to set `elideShort` to
   505  // false. The reason a number of entries is needed is that we may be
   506  // eliding a subtree of causes in the case of a multi-cause error. In
   507  // the multi-cause case, we need to know how many of the prior errors
   508  // in the list of entries is a child of this subtree.
   509  func (s *state) elideShortChildren(newEntries int) {
   510  	for i := 0; i < newEntries; i++ {
   511  		s.entries[len(s.entries)-1-i].elideShort = true
   512  	}
   513  }
   514  
   515  func (s *state) collectEntry(err error, bufIsRedactable bool, withDepth bool, depth int) formatEntry {
   516  	entry := formatEntry{err: err}
   517  	if s.wantDetail {
   518  		// The buffer has been populated as a result of formatting with
   519  		// %+v. In that case, if the printer has separated detail
   520  		// from non-detail, we can use the split.
   521  		if s.hasDetail {
   522  			entry.head = s.headBuf
   523  			entry.details = s.buf.Bytes()
   524  		} else {
   525  			entry.head = s.buf.Bytes()
   526  		}
   527  	} else {
   528  		entry.head = s.headBuf
   529  		if len(entry.head) > 0 && entry.head[len(entry.head)-1] != '\n' &&
   530  			s.buf.Len() > 0 && s.buf.Bytes()[0] != '\n' {
   531  			entry.head = append(entry.head, '\n')
   532  		}
   533  		entry.head = append(entry.head, s.buf.Bytes()...)
   534  	}
   535  
   536  	if bufIsRedactable {
   537  		// In this case, we've produced entry.head/entry.details using a
   538  		// SafeFormatError() invocation. The strings in
   539  		// entry.head/entry.detail contain redaction markers at this
   540  		// point.
   541  		if s.redactableOutput {
   542  			// Redaction markers desired in the final output. Keep the
   543  			// redaction markers.
   544  			entry.redactable = true
   545  		} else {
   546  			// Markers not desired in the final output: strip the markers.
   547  			entry.head = redact.RedactableBytes(entry.head).StripMarkers()
   548  			entry.details = redact.RedactableBytes(entry.details).StripMarkers()
   549  		}
   550  	}
   551  
   552  	if withDepth {
   553  		entry.depth = depth
   554  	}
   555  
   556  	return entry
   557  }
   558  
   559  // safeErrorPrinterFn is the type of a function that can take
   560  // over the safe printing of an error. This is used to inject special
   561  // cases into the formatting in errutil. We need this machinery to
   562  // prevent import cycles.
   563  type safeErrorPrinterFn = func(err error, p Printer, isLeaf bool) (handled bool, next error)
   564  
   565  // specialCases is a list of functions to apply for special cases.
   566  var specialCases []safeErrorPrinterFn
   567  
   568  // RegisterSpecialCasePrinter registers a handler.
   569  func RegisterSpecialCasePrinter(fn safeErrorPrinterFn) {
   570  	specialCases = append(specialCases, fn)
   571  }
   572  
   573  // formatSimple performs a best effort at extracting the details at a
   574  // given level of wrapping when the error object does not implement
   575  // the Formatter interface.
   576  // Returns true if we want to elide errors from causal chain.
   577  func (s *state) formatSimple(err, cause error) bool {
   578  	var pref string
   579  	elideCauses := false
   580  	if cause != nil {
   581  		var messageType MessageType
   582  		pref, messageType = extractPrefix(err, cause)
   583  		if messageType == FullMessage {
   584  			elideCauses = true
   585  		}
   586  	} else {
   587  		pref = err.Error()
   588  	}
   589  	if len(pref) > 0 {
   590  		s.Write([]byte(pref))
   591  	}
   592  	return elideCauses
   593  }
   594  
   595  // finishDisplay renders s.finalBuf into s.State.
   596  func (p *state) finishDisplay(verb rune) {
   597  	if p.redactableOutput {
   598  		// If we're rendering in redactable form, then s.finalBuf contains
   599  		// a RedactableBytes. We can emit that directly.
   600  		sp := p.State.(redact.SafePrinter)
   601  		sp.Print(redact.RedactableBytes(p.finalBuf.Bytes()))
   602  		return
   603  	}
   604  	// Not redactable: render depending on flags and verb.
   605  
   606  	width, okW := p.Width()
   607  	_, okP := p.Precision()
   608  
   609  	// If `direct` is set to false, then the buffer is always
   610  	// passed through fmt.Printf regardless of the width and alignment
   611  	// settings. This is important for e.g. %q where quotes must be added
   612  	// in any case.
   613  	// If `direct` is set to true, then the detour via
   614  	// fmt.Printf only occurs if there is a width or alignment
   615  	// specifier.
   616  	direct := verb == 'v' || verb == 's'
   617  
   618  	if !direct || (okW && width > 0) || okP {
   619  		_, format := redact.MakeFormat(p, verb)
   620  		fmt.Fprintf(p.State, format, p.finalBuf.String())
   621  	} else {
   622  		io.Copy(p.State, &p.finalBuf)
   623  	}
   624  }
   625  
   626  var detailSep = []byte("\n  | ")
   627  
   628  // state tracks error printing state. It implements fmt.State.
   629  type state struct {
   630  	// state inherits fmt.State.
   631  	//
   632  	// If we are rendering with redactableOutput=true, then fmt.State
   633  	// can be downcasted to redact.SafePrinter.
   634  	fmt.State
   635  
   636  	// redactableOutput indicates whether we want the output
   637  	// to use redaction markers. When set to true,
   638  	// the fmt.State above is actually a redact.SafePrinter.
   639  	redactableOutput bool
   640  
   641  	// finalBuf contains the final rendered string, prior to being
   642  	// copied to the fmt.State above.
   643  	//
   644  	// If redactableOutput is true, then finalBuf contains a RedactableBytes
   645  	// and safe redaction markers. Otherwise, it can be considered
   646  	// an unsafe string.
   647  	finalBuf bytes.Buffer
   648  
   649  	// entries collect the result of formatRecursive(). They are
   650  	// consumed by formatSingleLineOutput() and formatEntries() to
   651  	// produce the contents of finalBuf.
   652  	entries []formatEntry
   653  
   654  	// buf collects the details of the current error object at a given
   655  	// stage of recursion in formatRecursive().
   656  	//
   657  	// At each stage of recursion (level of wrapping), buf contains
   658  	// successively:
   659  	//
   660  	// - at the beginning, the "simple" part of the error message --
   661  	//   either the pre-Detail() string if the error implements Formatter,
   662  	//   or the result of Error().
   663  	//
   664  	// - after the first call to Detail(), buf is copied to headBuf,
   665  	//   then reset, then starts collecting the "advanced" part of the
   666  	//   error message.
   667  	//
   668  	// At the end of an error layer, the contents of buf and headBuf
   669  	// are collected into a formatEntry by collectEntry().
   670  	// This collection does not touch finalBuf above.
   671  	//
   672  	// The entries are later consumed by formatSingleLineOutput() or
   673  	// formatEntries() to produce the contents of finalBuf.
   674  	//
   675  	//
   676  	// Notes regarding redaction markers and string safety. Throughout a
   677  	// single "level" of error, there are three cases to consider:
   678  	//
   679  	// - the error level implements SafeErrorFormatter and
   680  	//   s.redactableOutput is set. In that case, the error's
   681  	//   SafeErrorFormat() is used to produce a RedactableBytes in
   682  	//   buf/headBuf via safePrinter{}, and an entry is collected at the
   683  	//   end of that with the redactable bit set on the entry.
   684  	//
   685  	// - the error level implements SafeErrorFormatter
   686  	//   and s.redactableOutput is *not* set. In this case,
   687  	//   for convenience we implement non-redactable output by using
   688  	//   SafeErrorFormat() to generate a RedactableBytes into
   689  	//   buf/headBuf via safePrinter{}, and then stripping the redaction
   690  	//   markers to produce the entry. The entry is not marked as
   691  	//   redactable.
   692  	//
   693  	// - in the remaining case (s.redactableOutput is not set or the
   694  	//   error only implements Formatter), then we use FormatError()
   695  	//   to produce a non-redactable string into buf/headBuf,
   696  	//   and mark the resulting entry as non-redactable.
   697  	buf bytes.Buffer
   698  	// When an error's FormatError() calls Detail(), the current
   699  	// value of buf above is copied to headBuf, and a new
   700  	// buf is initialized.
   701  	headBuf []byte
   702  
   703  	// lastStack tracks the last stack trace observed when looking at
   704  	// the errors from innermost to outermost. This is used to elide
   705  	// redundant stack trace entries.
   706  	lastStack StackTrace
   707  
   708  	// ---------------------------------------------------------------
   709  	// The following attributes organize the synchronization of writes
   710  	// to buf and headBuf, during the rendering of a single error
   711  	// layer. They get reset between layers.
   712  
   713  	// hasDetail becomes true at each level of the formatRecursive()
   714  	// recursion after the first call to .Detail(). It is used to
   715  	// determine how to translate buf/headBuf into a formatEntry.
   716  	hasDetail bool
   717  
   718  	// wantDetail is set to true when the error is formatted via %+v.
   719  	// When false, printer.Detail() will always return false and the
   720  	// error's .FormatError() method can perform less work. (This is an
   721  	// optimization for the common case when an error's .Error() method
   722  	// delegates its work to its .FormatError() via fmt.Format and
   723  	// errors.FormatError().)
   724  	wantDetail bool
   725  
   726  	// collectingRedactableString is true iff the data being accumulated
   727  	// into buf comes from a redact string. It ensures that newline
   728  	// characters are not included inside redaction markers.
   729  	collectingRedactableString bool
   730  
   731  	// notEmpty tracks, at each level of recursion of formatRecursive(),
   732  	// whether there were any details printed by an error's
   733  	// .FormatError() method. It is used to properly determine whether
   734  	// the printout should start with a newline and padding.
   735  	notEmpty bool
   736  	// needSpace tracks whether the next character displayed should pad
   737  	// using a space character.
   738  	needSpace bool
   739  	// needNewline tracks whether the next character displayed should
   740  	// pad using a newline and indentation.
   741  	needNewline int
   742  	// multiLine tracks whether the details so far contain multiple
   743  	// lines. It is used to determine whether an enclosed stack trace,
   744  	// if any, should be introduced with a separator.
   745  	multiLine bool
   746  }
   747  
   748  // formatEntry collects the textual details about one level of
   749  // wrapping or the leaf error in an error chain.
   750  type formatEntry struct {
   751  	err error
   752  	// redactable is true iff the data in head and details
   753  	// are RedactableBytes. See the explanatory comments
   754  	// on (state).buf for when this is set.
   755  	redactable bool
   756  	// head is the part of the text that is suitable for printing in the
   757  	// one-liner summary, or when producing the output of .Error().
   758  	head []byte
   759  	// details is the part of the text produced in the advanced output
   760  	// included for `%+v` formats.
   761  	details []byte
   762  	// elideShort, if true, elides the value of 'head' from concatenated
   763  	// "short" messages produced by formatSingleLineOutput().
   764  	elideShort bool
   765  
   766  	// stackTrace, if non-nil, reports the stack trace embedded at this
   767  	// level of error.
   768  	stackTrace StackTrace
   769  	// elidedStackTrace, if true, indicates that the stack trace was
   770  	// truncated to avoid duplication of entries. This is used to
   771  	// display a truncation indicator during verbose rendering.
   772  	elidedStackTrace bool
   773  
   774  	// depth, if positive, represents a nesting depth of this error as
   775  	// a causer of others. This is used with verbose printing to
   776  	// illustrate the nesting depth for multi-cause error wrappers.
   777  	depth int
   778  }
   779  
   780  // String is used for debugging only.
   781  func (e formatEntry) String() string {
   782  	return fmt.Sprintf("formatEntry{%T, %q, %q}", e.err, e.head, e.details)
   783  }
   784  
   785  // Write implements io.Writer.
   786  func (s *state) Write(b []byte) (n int, err error) {
   787  	if len(b) == 0 {
   788  		return 0, nil
   789  	}
   790  	k := 0
   791  
   792  	sep := detailSep
   793  	if !s.wantDetail {
   794  		sep = []byte("\n")
   795  	}
   796  
   797  	for i, c := range b {
   798  		if c == '\n' {
   799  			//if s.needNewline > 0 {
   800  			//	for i := 0; i < s.needNewline-1; i++ {
   801  			//		s.buf.Write(detailSep[:len(sep)-1])
   802  			//	}
   803  			//	s.needNewline = 0
   804  			//}
   805  			// Flush all the bytes seen so far.
   806  			s.buf.Write(b[k:i])
   807  			// Don't print the newline itself; instead, prepare the state so
   808  			// that the _next_ character encountered will pad with a newline.
   809  			// This algorithm avoids terminating error details with excess
   810  			// newline characters.
   811  			k = i + 1
   812  			s.needNewline++
   813  			s.needSpace = false
   814  			s.multiLine = true
   815  			if s.wantDetail {
   816  				s.switchOver()
   817  			}
   818  		} else {
   819  			if s.needNewline > 0 && s.notEmpty {
   820  				// If newline chars were pending, display them now.
   821  				for i := 0; i < s.needNewline-1; i++ {
   822  					s.buf.Write(detailSep[:len(sep)-1])
   823  				}
   824  				s.buf.Write(sep)
   825  				s.needNewline = 0
   826  				s.needSpace = false
   827  			} else if s.needSpace {
   828  				s.buf.WriteByte(' ')
   829  				s.needSpace = false
   830  			}
   831  			s.notEmpty = true
   832  		}
   833  	}
   834  	//if s.needNewline > 0 {
   835  	//	for i := 0; i < s.needNewline-1; i++ {
   836  	//		s.buf.Write(detailSep[:len(sep)-1])
   837  	//	}
   838  	//}
   839  	s.buf.Write(b[k:])
   840  	return len(b), nil
   841  }
   842  
   843  // printer wraps a state to implement an xerrors.Printer.
   844  type printer state
   845  
   846  func (p *state) detail() bool {
   847  	if !p.wantDetail {
   848  		return false
   849  	}
   850  	if p.notEmpty {
   851  		p.needNewline = 1
   852  	}
   853  	p.switchOver()
   854  	return true
   855  }
   856  
   857  func (p *state) switchOver() {
   858  	if p.hasDetail {
   859  		return
   860  	}
   861  	p.headBuf = p.buf.Bytes()
   862  	p.buf = bytes.Buffer{}
   863  	p.notEmpty = false
   864  	p.hasDetail = true
   865  
   866  	// One of the newlines is accounted for in the switch over.
   867  	// p.needNewline -= 1
   868  }
   869  
   870  func (s *printer) Detail() bool {
   871  	return ((*state)(s)).detail()
   872  }
   873  
   874  func (s *printer) Print(args ...interface{}) {
   875  	s.enhanceArgs(args)
   876  	fmt.Fprint((*state)(s), args...)
   877  }
   878  
   879  func (s *printer) Printf(format string, args ...interface{}) {
   880  	s.enhanceArgs(args)
   881  	fmt.Fprintf((*state)(s), format, args...)
   882  }
   883  
   884  func (s *printer) enhanceArgs(args []interface{}) {
   885  	prevStack := s.lastStack
   886  	lastSeen := prevStack
   887  	for i := range args {
   888  		if st, ok := args[i].(pkgErr.StackTrace); ok {
   889  			args[i], _ = ElideSharedStackTraceSuffix(prevStack, st)
   890  			lastSeen = st
   891  		}
   892  		if err, ok := args[i].(error); ok {
   893  			args[i] = &errorFormatter{err}
   894  		}
   895  	}
   896  	s.lastStack = lastSeen
   897  }
   898  
   899  // safePrinter is a variant to printer used when the current error
   900  // level implements SafeFormatter.
   901  //
   902  // In any case, it uses the error's SafeFormatError() method to
   903  // prepare a RedactableBytes into s.buf / s.headBuf.
   904  // The the explanation for `buf` in the state struct.
   905  type safePrinter state
   906  
   907  func (s *safePrinter) Detail() bool {
   908  	return ((*state)(s)).detail()
   909  }
   910  
   911  func (s *safePrinter) Print(args ...interface{}) {
   912  	s.enhanceArgs(args)
   913  	redact.Fprint((*state)(s), args...)
   914  }
   915  
   916  func (s *safePrinter) Printf(format string, args ...interface{}) {
   917  	s.enhanceArgs(args)
   918  	redact.Fprintf((*state)(s), format, args...)
   919  }
   920  
   921  func (s *safePrinter) enhanceArgs(args []interface{}) {
   922  	prevStack := s.lastStack
   923  	lastSeen := prevStack
   924  	for i := range args {
   925  		if st, ok := args[i].(pkgErr.StackTrace); ok {
   926  			thisStack, _ := ElideSharedStackTraceSuffix(prevStack, st)
   927  			// Stack traces are safe strings.
   928  			args[i] = redact.Safe(thisStack)
   929  			lastSeen = st
   930  		}
   931  		// In contrast with (*printer).enhanceArgs(), we don't use a
   932  		// special case for `error` here, because the redact package
   933  		// already helps us recursing into a safe print for
   934  		// error objects.
   935  	}
   936  	s.lastStack = lastSeen
   937  }
   938  
   939  type errorFormatter struct{ err error }
   940  
   941  // Format implements the fmt.Formatter interface.
   942  func (ef *errorFormatter) Format(s fmt.State, verb rune) { FormatError(ef.err, s, verb) }
   943  
   944  // Error implements error, so that `redact` knows what to do with it.
   945  func (ef *errorFormatter) Error() string { return ef.err.Error() }
   946  
   947  // Unwrap makes it a wrapper.
   948  func (ef *errorFormatter) Unwrap() error { return ef.err }
   949  
   950  // Cause makes it a wrapper.
   951  func (ef *errorFormatter) Cause() error { return ef.err }
   952  
   953  // ElideSharedStackTraceSuffix removes the suffix of newStack that's already
   954  // present in prevStack. The function returns true if some entries
   955  // were elided.
   956  func ElideSharedStackTraceSuffix(prevStack, newStack StackTrace) (StackTrace, bool) {
   957  	if len(prevStack) == 0 {
   958  		return newStack, false
   959  	}
   960  	if len(newStack) == 0 {
   961  		return newStack, false
   962  	}
   963  
   964  	// Skip over the common suffix.
   965  	var i, j int
   966  	for i, j = len(newStack)-1, len(prevStack)-1; i > 0 && j > 0; i, j = i-1, j-1 {
   967  		if newStack[i] != prevStack[j] {
   968  			break
   969  		}
   970  	}
   971  	if i == 0 {
   972  		// Keep at least one entry.
   973  		i = 1
   974  	}
   975  	return newStack[:i], i < len(newStack)-1
   976  }
   977  
   978  // StackTrace is the type of the data for a call stack.
   979  // This mirrors the type of the same name in github.com/pkg/errors.
   980  type StackTrace = pkgErr.StackTrace
   981  
   982  // StackFrame is the type of a single call frame entry.
   983  // This mirrors the type of the same name in github.com/pkg/errors.
   984  type StackFrame = pkgErr.Frame
   985  
   986  // StackTraceProvider is a provider of StackTraces.
   987  // This is, intendedly, defined to be implemented by pkg/errors.stack.
   988  type StackTraceProvider interface {
   989  	StackTrace() StackTrace
   990  }