...

Source file src/cloud.google.com/go/internal/pretty/pretty.go

Documentation: cloud.google.com/go/internal/pretty

     1  // Copyright 2016 Google LLC
     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 implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package pretty implements a simple pretty-printer. It is intended for
    16  // debugging the output of tests.
    17  //
    18  // It follows pointers and produces multi-line output for complex values like
    19  // slices, maps and structs.
    20  package pretty
    21  
    22  import (
    23  	"fmt"
    24  	"io"
    25  	"reflect"
    26  	"sort"
    27  	"strings"
    28  	"time"
    29  )
    30  
    31  // Indent is the string output at each level of indentation.
    32  var Indent = "    "
    33  
    34  // Value returns a value that will print prettily when used as an
    35  // argument for the %v or %s format specifiers.
    36  // With no flags, struct fields and map keys with default values are omitted.
    37  // With the '+' or '#' flags, all values are displayed.
    38  //
    39  // This package does not detect cycles. Attempting to print a Value that
    40  // contains cycles will result in unbounded recursion.
    41  func Value(v interface{}) val { return val{v: v} }
    42  
    43  // val is a value.
    44  type val struct{ v interface{} }
    45  
    46  // Format implements the fmt.Formatter interface.
    47  func (v val) Format(s fmt.State, c rune) {
    48  	if c == 'v' || c == 's' {
    49  		fprint(s, reflect.ValueOf(v.v), state{
    50  			defaults: s.Flag('+') || s.Flag('#'),
    51  		})
    52  	} else {
    53  		fmt.Fprintf(s, "%%!%c(pretty.val)", c)
    54  	}
    55  }
    56  
    57  type state struct {
    58  	level          int
    59  	prefix, suffix string
    60  	defaults       bool
    61  }
    62  
    63  const maxLevel = 100
    64  
    65  var typeOfTime = reflect.TypeOf(time.Time{})
    66  
    67  func fprint(w io.Writer, v reflect.Value, s state) {
    68  	if s.level > maxLevel {
    69  		fmt.Fprintln(w, "pretty: max nested depth exceeded")
    70  		return
    71  	}
    72  	indent := strings.Repeat(Indent, s.level)
    73  	fmt.Fprintf(w, "%s%s", indent, s.prefix)
    74  	if isNil(v) {
    75  		fmt.Fprintf(w, "nil%s", s.suffix)
    76  		return
    77  	}
    78  	if v.Type().Kind() == reflect.Interface {
    79  		v = v.Elem()
    80  	}
    81  	if v.Type() == typeOfTime {
    82  		fmt.Fprintf(w, "%s%s", v.Interface(), s.suffix)
    83  		return
    84  	}
    85  	for v.Type().Kind() == reflect.Ptr {
    86  		fmt.Fprintf(w, "&")
    87  		v = v.Elem()
    88  	}
    89  	switch v.Type().Kind() {
    90  	default:
    91  		fmt.Fprintf(w, "%s%s", short(v), s.suffix)
    92  
    93  	case reflect.Array:
    94  		fmt.Fprintf(w, "%s{\n", v.Type())
    95  		for i := 0; i < v.Len(); i++ {
    96  			fprint(w, v.Index(i), state{
    97  				level:    s.level + 1,
    98  				prefix:   "",
    99  				suffix:   ",",
   100  				defaults: s.defaults,
   101  			})
   102  			fmt.Fprintln(w)
   103  		}
   104  		fmt.Fprintf(w, "%s}", indent)
   105  
   106  	case reflect.Slice:
   107  		fmt.Fprintf(w, "%s{", v.Type())
   108  		if v.Len() > 0 {
   109  			fmt.Fprintln(w)
   110  			for i := 0; i < v.Len(); i++ {
   111  				fprint(w, v.Index(i), state{
   112  					level:    s.level + 1,
   113  					prefix:   "",
   114  					suffix:   ",",
   115  					defaults: s.defaults,
   116  				})
   117  				fmt.Fprintln(w)
   118  			}
   119  		}
   120  		fmt.Fprintf(w, "%s}%s", indent, s.suffix)
   121  
   122  	case reflect.Map:
   123  		fmt.Fprintf(w, "%s{", v.Type())
   124  		if v.Len() > 0 {
   125  			fmt.Fprintln(w)
   126  			keys := v.MapKeys()
   127  			maybeSort(keys, v.Type().Key())
   128  			for _, key := range keys {
   129  				val := v.MapIndex(key)
   130  				if s.defaults || !isDefault(val) {
   131  					fprint(w, val, state{
   132  						level:    s.level + 1,
   133  						prefix:   short(key) + ": ",
   134  						suffix:   ",",
   135  						defaults: s.defaults,
   136  					})
   137  					fmt.Fprintln(w)
   138  				}
   139  			}
   140  		}
   141  		fmt.Fprintf(w, "%s}%s", indent, s.suffix)
   142  
   143  	case reflect.Struct:
   144  		t := v.Type()
   145  		fmt.Fprintf(w, "%s{\n", t)
   146  		for i := 0; i < t.NumField(); i++ {
   147  			f := v.Field(i)
   148  			if s.defaults || !isDefault(f) {
   149  				fprint(w, f, state{
   150  					level:    s.level + 1,
   151  					prefix:   t.Field(i).Name + ": ",
   152  					suffix:   ",",
   153  					defaults: s.defaults,
   154  				})
   155  				fmt.Fprintln(w)
   156  			}
   157  		}
   158  		fmt.Fprintf(w, "%s}%s", indent, s.suffix)
   159  	}
   160  }
   161  
   162  func isNil(v reflect.Value) bool {
   163  	if !v.IsValid() {
   164  		return true
   165  	}
   166  	switch v.Type().Kind() {
   167  	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
   168  		return v.IsNil()
   169  	default:
   170  		return false
   171  	}
   172  }
   173  
   174  func isDefault(v reflect.Value) bool {
   175  	if !v.IsValid() {
   176  		return true
   177  	}
   178  	t := v.Type()
   179  	switch t.Kind() {
   180  	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
   181  		return v.IsNil()
   182  	default:
   183  		if !v.CanInterface() {
   184  			return false
   185  		}
   186  		return t.Comparable() && v.Interface() == reflect.Zero(t).Interface()
   187  	}
   188  }
   189  
   190  // short returns a short, one-line string for v.
   191  func short(v reflect.Value) string {
   192  	if !v.IsValid() {
   193  		return "nil"
   194  	}
   195  	if v.Type().Kind() == reflect.String {
   196  		return fmt.Sprintf("%q", v)
   197  	}
   198  	return fmt.Sprintf("%v", v)
   199  }
   200  
   201  func maybeSort(vs []reflect.Value, t reflect.Type) {
   202  	if less := lessFunc(t); less != nil {
   203  		sort.Sort(&sorter{vs, less})
   204  	}
   205  }
   206  
   207  // lessFunc returns a function that implements the "<" operator
   208  // for the given type, or nil if the type doesn't support "<" .
   209  func lessFunc(t reflect.Type) func(v1, v2 interface{}) bool {
   210  	switch t.Kind() {
   211  	case reflect.String:
   212  		return func(v1, v2 interface{}) bool { return v1.(string) < v2.(string) }
   213  	case reflect.Int:
   214  		return func(v1, v2 interface{}) bool { return v1.(int) < v2.(int) }
   215  	case reflect.Int8:
   216  		return func(v1, v2 interface{}) bool { return v1.(int8) < v2.(int8) }
   217  	case reflect.Int16:
   218  		return func(v1, v2 interface{}) bool { return v1.(int16) < v2.(int16) }
   219  	case reflect.Int32:
   220  		return func(v1, v2 interface{}) bool { return v1.(int32) < v2.(int32) }
   221  	case reflect.Int64:
   222  		return func(v1, v2 interface{}) bool { return v1.(int64) < v2.(int64) }
   223  	case reflect.Uint:
   224  		return func(v1, v2 interface{}) bool { return v1.(uint) < v2.(uint) }
   225  	case reflect.Uint8:
   226  		return func(v1, v2 interface{}) bool { return v1.(uint8) < v2.(uint8) }
   227  	case reflect.Uint16:
   228  		return func(v1, v2 interface{}) bool { return v1.(uint16) < v2.(uint16) }
   229  	case reflect.Uint32:
   230  		return func(v1, v2 interface{}) bool { return v1.(uint32) < v2.(uint32) }
   231  	case reflect.Uint64:
   232  		return func(v1, v2 interface{}) bool { return v1.(uint64) < v2.(uint64) }
   233  	case reflect.Float32:
   234  		return func(v1, v2 interface{}) bool { return v1.(float32) < v2.(float32) }
   235  	case reflect.Float64:
   236  		return func(v1, v2 interface{}) bool { return v1.(float64) < v2.(float64) }
   237  	default:
   238  		return nil
   239  	}
   240  }
   241  
   242  type sorter struct {
   243  	vs   []reflect.Value
   244  	less func(v1, v2 interface{}) bool
   245  }
   246  
   247  func (s *sorter) Len() int           { return len(s.vs) }
   248  func (s *sorter) Swap(i, j int)      { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
   249  func (s *sorter) Less(i, j int) bool { return s.less(s.vs[i].Interface(), s.vs[j].Interface()) }
   250  

View as plain text