490 lines
13 KiB
Diff
490 lines
13 KiB
Diff
--- print.go.orig 2021-06-18 16:45:56.623967000 +0200
|
|
+++ print.go 2021-06-19 16:26:32.751061000 +0200
|
|
@@ -1,16 +1,27 @@
|
|
+// Code generated from print.go.orig. DO NOT EDIT
|
|
+// GENERATED FILE DO NOT EDIT
|
|
+//
|
|
// Copyright 2009 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 fmt
|
|
+package rfmt
|
|
|
|
import (
|
|
- "internal/fmtsort"
|
|
+ // CUSTOM: needed to avoid a type mismatch on Formatter.
|
|
+ origFmt "fmt"
|
|
"io"
|
|
"os"
|
|
"reflect"
|
|
"sync"
|
|
"unicode/utf8"
|
|
+
|
|
+ // CUSTOM: our own imports.
|
|
+ i "github.com/cockroachdb/redact/interfaces"
|
|
+ b "github.com/cockroachdb/redact/internal/buffer"
|
|
+ m "github.com/cockroachdb/redact/internal/markers"
|
|
+ w "github.com/cockroachdb/redact/internal/redact"
|
|
+ "github.com/cockroachdb/redact/internal/rfmt/fmtsort"
|
|
)
|
|
|
|
// Strings for use with buffer.WriteString.
|
|
@@ -51,7 +62,8 @@
|
|
// The implementation controls how State and rune are interpreted,
|
|
// and may call Sprint(f) or Fprint(f) etc. to generate its output.
|
|
type Formatter interface {
|
|
- Format(f State, verb rune)
|
|
+ // CUSTOM: refer to the original type, not the one defined here.
|
|
+ Format(f origFmt.State, verb rune)
|
|
}
|
|
|
|
// Stringer is implemented by any value that has a String method,
|
|
@@ -71,40 +83,34 @@
|
|
GoString() string
|
|
}
|
|
|
|
-// Use simple []byte instead of bytes.Buffer to avoid large dependency.
|
|
-type buffer []byte
|
|
+// CUSTOM: smarter buffer.
|
|
+type buffer struct {
|
|
+ b.Buffer
|
|
+}
|
|
|
|
func (b *buffer) write(p []byte) {
|
|
- *b = append(*b, p...)
|
|
+ b.Write(p)
|
|
}
|
|
|
|
func (b *buffer) writeString(s string) {
|
|
- *b = append(*b, s...)
|
|
+ b.WriteString(s)
|
|
}
|
|
|
|
func (b *buffer) writeByte(c byte) {
|
|
- *b = append(*b, c)
|
|
+ b.WriteByte(c)
|
|
}
|
|
|
|
func (bp *buffer) writeRune(r rune) {
|
|
- if r < utf8.RuneSelf {
|
|
- *bp = append(*bp, byte(r))
|
|
- return
|
|
- }
|
|
-
|
|
- b := *bp
|
|
- n := len(b)
|
|
- for n+utf8.UTFMax > cap(b) {
|
|
- b = append(b, 0)
|
|
- }
|
|
- w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r)
|
|
- *bp = b[:n+w]
|
|
+ bp.WriteRune(r)
|
|
}
|
|
|
|
// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.
|
|
type pp struct {
|
|
buf buffer
|
|
|
|
+ // CUSTOM: override safety in recursive calls.
|
|
+ override overrideMode
|
|
+
|
|
// arg holds the current item, as an interface{}.
|
|
arg interface{}
|
|
|
|
@@ -150,11 +156,11 @@
|
|
// to place back in the pool.
|
|
//
|
|
// See https://golang.org/issue/23199
|
|
- if cap(p.buf) > 64<<10 {
|
|
+ if p.buf.Cap() > 64<<10 {
|
|
return
|
|
}
|
|
|
|
- p.buf = p.buf[:0]
|
|
+ p.buf.Reset()
|
|
p.arg = nil
|
|
p.value = reflect.Value{}
|
|
p.wrappedErr = nil
|
|
@@ -183,14 +189,16 @@
|
|
|
|
// Implement Write so we can call Fprintf on a pp (through State), for
|
|
// recursive use in custom verbs.
|
|
-func (p *pp) Write(b []byte) (ret int, err error) {
|
|
- p.buf.write(b)
|
|
- return len(b), nil
|
|
+func (p *pp) Write(bs []byte) (ret int, err error) {
|
|
+ defer p.startUnsafe().restore()
|
|
+ p.buf.write(bs)
|
|
+ return len(bs), nil
|
|
}
|
|
|
|
// Implement WriteString so that we can call io.WriteString
|
|
// on a pp (through state), for efficiency.
|
|
func (p *pp) WriteString(s string) (ret int, err error) {
|
|
+ defer p.startUnsafe().restore()
|
|
p.buf.writeString(s)
|
|
return len(s), nil
|
|
}
|
|
@@ -202,7 +210,7 @@
|
|
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
|
p := newPrinter()
|
|
p.doPrintf(format, a)
|
|
- n, err = w.Write(p.buf)
|
|
+ n, err = w.Write([]byte(p.buf.TakeRedactableBytes()))
|
|
p.free()
|
|
return
|
|
}
|
|
@@ -214,10 +222,10 @@
|
|
}
|
|
|
|
// Sprintf formats according to a format specifier and returns the resulting string.
|
|
-func Sprintf(format string, a ...interface{}) string {
|
|
+func Sprintf(format string, a ...interface{}) m.RedactableString {
|
|
p := newPrinter()
|
|
p.doPrintf(format, a)
|
|
- s := string(p.buf)
|
|
+ s := p.buf.TakeRedactableString()
|
|
p.free()
|
|
return s
|
|
}
|
|
@@ -230,7 +238,7 @@
|
|
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
|
p := newPrinter()
|
|
p.doPrint(a)
|
|
- n, err = w.Write(p.buf)
|
|
+ n, err = w.Write([]byte(p.buf.TakeRedactableBytes()))
|
|
p.free()
|
|
return
|
|
}
|
|
@@ -244,10 +252,10 @@
|
|
|
|
// Sprint formats using the default formats for its operands and returns the resulting string.
|
|
// Spaces are added between operands when neither is a string.
|
|
-func Sprint(a ...interface{}) string {
|
|
+func Sprint(a ...interface{}) m.RedactableString {
|
|
p := newPrinter()
|
|
p.doPrint(a)
|
|
- s := string(p.buf)
|
|
+ s := p.buf.TakeRedactableString()
|
|
p.free()
|
|
return s
|
|
}
|
|
@@ -262,7 +270,7 @@
|
|
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
|
p := newPrinter()
|
|
p.doPrintln(a)
|
|
- n, err = w.Write(p.buf)
|
|
+ n, err = w.Write([]byte(p.buf.TakeRedactableBytes()))
|
|
p.free()
|
|
return
|
|
}
|
|
@@ -276,10 +284,10 @@
|
|
|
|
// Sprintln formats using the default formats for its operands and returns the resulting string.
|
|
// Spaces are always added between operands and a newline is appended.
|
|
-func Sprintln(a ...interface{}) string {
|
|
+func Sprintln(a ...interface{}) m.RedactableString {
|
|
p := newPrinter()
|
|
p.doPrintln(a)
|
|
- s := string(p.buf)
|
|
+ s := p.buf.TakeRedactableString()
|
|
p.free()
|
|
return s
|
|
}
|
|
@@ -351,6 +359,7 @@
|
|
func (p *pp) fmtBool(v bool, verb rune) {
|
|
switch verb {
|
|
case 't', 'v':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtBoolean(v)
|
|
default:
|
|
p.badVerb(verb)
|
|
@@ -362,6 +371,7 @@
|
|
func (p *pp) fmt0x64(v uint64, leading0x bool) {
|
|
sharp := p.fmt.sharp
|
|
p.fmt.sharp = leading0x
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits)
|
|
p.fmt.sharp = sharp
|
|
}
|
|
@@ -373,23 +383,32 @@
|
|
if p.fmt.sharpV && !isSigned {
|
|
p.fmt0x64(v, true)
|
|
} else {
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
|
|
}
|
|
case 'd':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
|
|
case 'b':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits)
|
|
case 'o', 'O':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits)
|
|
case 'x':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits)
|
|
case 'X':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtInteger(v, 16, isSigned, verb, udigits)
|
|
case 'c':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtC(v)
|
|
case 'q':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtQc(v)
|
|
case 'U':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtUnicode(v)
|
|
default:
|
|
p.badVerb(verb)
|
|
@@ -401,12 +420,16 @@
|
|
func (p *pp) fmtFloat(v float64, size int, verb rune) {
|
|
switch verb {
|
|
case 'v':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtFloat(v, size, 'g', -1)
|
|
case 'b', 'g', 'G', 'x', 'X':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtFloat(v, size, verb, -1)
|
|
case 'f', 'e', 'E':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtFloat(v, size, verb, 6)
|
|
case 'F':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtFloat(v, size, 'f', 6)
|
|
default:
|
|
p.badVerb(verb)
|
|
@@ -437,18 +460,23 @@
|
|
func (p *pp) fmtString(v string, verb rune) {
|
|
switch verb {
|
|
case 'v':
|
|
+ defer p.startUnsafe().restore()
|
|
if p.fmt.sharpV {
|
|
p.fmt.fmtQ(v)
|
|
} else {
|
|
p.fmt.fmtS(v)
|
|
}
|
|
case 's':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtS(v)
|
|
case 'x':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtSx(v, ldigits)
|
|
case 'X':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtSx(v, udigits)
|
|
case 'q':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtQ(v)
|
|
default:
|
|
p.badVerb(verb)
|
|
@@ -478,17 +506,24 @@
|
|
if i > 0 {
|
|
p.buf.writeByte(' ')
|
|
}
|
|
- p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits)
|
|
+ func(p *pp, c byte, verb rune) {
|
|
+ defer p.startUnsafe().restore()
|
|
+ p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits)
|
|
+ }(p, c, verb)
|
|
}
|
|
p.buf.writeByte(']')
|
|
}
|
|
case 's':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtBs(v)
|
|
case 'x':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtBx(v, ldigits)
|
|
case 'X':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtBx(v, udigits)
|
|
case 'q':
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtQ(string(v))
|
|
default:
|
|
p.printValue(reflect.ValueOf(v), verb, 0)
|
|
@@ -519,6 +554,7 @@
|
|
p.buf.writeByte(')')
|
|
} else {
|
|
if u == 0 {
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.padString(nilAngleString)
|
|
} else {
|
|
p.fmt0x64(uint64(u), !p.fmt.sharp)
|
|
@@ -586,10 +622,37 @@
|
|
verb = 'v'
|
|
}
|
|
|
|
+ if p.override != overrideUnsafe {
|
|
+ switch v := p.arg.(type) {
|
|
+ case i.SafeFormatter:
|
|
+ handled = true
|
|
+ defer p.catchPanic(p.arg, verb, "SafeFormat")
|
|
+ v.SafeFormat(p, verb)
|
|
+ return
|
|
+
|
|
+ case i.SafeMessager:
|
|
+ handled = true
|
|
+ defer p.catchPanic(p.arg, verb, "SafeMessager")
|
|
+ defer p.startSafeOverride().restore()
|
|
+ p.fmtString(v.SafeMessage(), verb)
|
|
+ return
|
|
+
|
|
+ case error:
|
|
+ if redactErrorFn != nil {
|
|
+ handled = true
|
|
+ defer p.catchPanic(p.arg, verb, "SafeFormatter")
|
|
+ redactErrorFn(v, p, verb)
|
|
+ return
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
// Is it a Formatter?
|
|
if formatter, ok := p.arg.(Formatter); ok {
|
|
handled = true
|
|
defer p.catchPanic(p.arg, verb, "Format")
|
|
+ // The mode is implicit: the Format() call will
|
|
+ // use p.Write() which already sets the mode.
|
|
formatter.Format(p, verb)
|
|
return
|
|
}
|
|
@@ -600,6 +663,7 @@
|
|
handled = true
|
|
defer p.catchPanic(p.arg, verb, "GoString")
|
|
// Print the result of GoString unadorned.
|
|
+ defer p.startUnsafe().restore()
|
|
p.fmt.fmtS(stringer.GoString())
|
|
return
|
|
}
|
|
@@ -632,6 +696,21 @@
|
|
}
|
|
|
|
func (p *pp) printArg(arg interface{}, verb rune) {
|
|
+ t := reflect.TypeOf(arg)
|
|
+ if safeTypeRegistry[t] {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ } else if t == safeWrapperType {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ arg = arg.(w.SafeWrapper).GetValue()
|
|
+ } else if t == unsafeWrapperType {
|
|
+ defer p.startUnsafeOverride().restore()
|
|
+ arg = arg.(w.UnsafeWrap).GetValue()
|
|
+ }
|
|
+
|
|
+ if _, ok := arg.(i.SafeValue); ok {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ }
|
|
+
|
|
p.arg = arg
|
|
p.value = reflect.Value{}
|
|
|
|
@@ -697,13 +776,35 @@
|
|
case reflect.Value:
|
|
// Handle extractable values with special methods
|
|
// since printValue does not handle them at depth 0.
|
|
- if f.IsValid() && f.CanInterface() {
|
|
- p.arg = f.Interface()
|
|
- if p.handleMethods(verb) {
|
|
+ if f.IsValid() {
|
|
+ t := f.Type()
|
|
+ if p.handleSpecialValues(f, t, verb, 0) {
|
|
return
|
|
}
|
|
+
|
|
+ if safeTypeRegistry[t] {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ }
|
|
+
|
|
+ if f.CanInterface() {
|
|
+ p.arg = f.Interface()
|
|
+ if _, ok := p.arg.(i.SafeValue); ok {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ }
|
|
+ if p.handleMethods(verb) {
|
|
+ return
|
|
+ }
|
|
+ }
|
|
}
|
|
p.printValue(f, verb, 0)
|
|
+ case m.RedactableString:
|
|
+ defer p.startPreRedactable().restore()
|
|
+ p.buf.WriteString(string(f))
|
|
+ return
|
|
+ case m.RedactableBytes:
|
|
+ defer p.startPreRedactable().restore()
|
|
+ p.buf.Write([]byte(f))
|
|
+ return
|
|
default:
|
|
// If the type is not simple, it might have methods.
|
|
if !p.handleMethods(verb) {
|
|
@@ -718,11 +819,25 @@
|
|
// It does not handle 'p' and 'T' verbs because these should have been already handled by printArg.
|
|
func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
|
|
// Handle values with special methods if not already handled by printArg (depth == 0).
|
|
- if depth > 0 && value.IsValid() && value.CanInterface() {
|
|
- p.arg = value.Interface()
|
|
- if p.handleMethods(verb) {
|
|
+ if depth > 0 && value.IsValid() {
|
|
+ t := value.Type()
|
|
+ if p.handleSpecialValues(value, t, verb, depth) {
|
|
return
|
|
}
|
|
+
|
|
+ if safeTypeRegistry[t] {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ }
|
|
+
|
|
+ if value.CanInterface() {
|
|
+ p.arg = value.Interface()
|
|
+ if _, ok := p.arg.(i.SafeValue); ok {
|
|
+ defer p.startSafeOverride().restore()
|
|
+ }
|
|
+ if p.handleMethods(verb) {
|
|
+ return
|
|
+ }
|
|
+ }
|
|
}
|
|
p.arg = nil
|
|
p.value = value
|
|
@@ -946,7 +1061,9 @@
|
|
// argNumber returns the next argument to evaluate, which is either the value of the passed-in
|
|
// argNum or the value of the bracketed integer that begins format[i:]. It also returns
|
|
// the new value of i, that is, the index of the next byte of the format to process.
|
|
-func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) {
|
|
+func (p *pp) argNumber(
|
|
+ argNum int, format string, i int, numArgs int,
|
|
+) (newArgNum, newi int, found bool) {
|
|
if len(format) <= i || format[i] != '[' {
|
|
return argNum, i, false
|
|
}
|
|
@@ -972,6 +1089,7 @@
|
|
}
|
|
|
|
func (p *pp) doPrintf(format string, a []interface{}) {
|
|
+ p.buf.SetMode(b.SafeEscaped)
|
|
end := len(format)
|
|
argNum := 0 // we process one argument per non-trivial format
|
|
afterIndex := false // previous item in format was an index like [3].
|
|
@@ -1147,6 +1265,7 @@
|
|
}
|
|
|
|
func (p *pp) doPrint(a []interface{}) {
|
|
+ p.buf.SetMode(b.SafeEscaped)
|
|
prevString := false
|
|
for argNum, arg := range a {
|
|
isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
|
|
@@ -1162,6 +1281,7 @@
|
|
// doPrintln is like doPrint but always adds a space between arguments
|
|
// and a newline after the last argument.
|
|
func (p *pp) doPrintln(a []interface{}) {
|
|
+ p.buf.SetMode(b.SafeEscaped)
|
|
for argNum, arg := range a {
|
|
if argNum > 0 {
|
|
p.buf.writeByte(' ')
|