diff options
Diffstat (limited to 'vendor/github.com/google/go-cmp/cmp/internal/value/format.go')
-rw-r--r-- | vendor/github.com/google/go-cmp/cmp/internal/value/format.go | 277 |
1 files changed, 0 insertions, 277 deletions
diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/format.go b/vendor/github.com/google/go-cmp/cmp/internal/value/format.go deleted file mode 100644 index 657e508..0000000 --- a/vendor/github.com/google/go-cmp/cmp/internal/value/format.go +++ /dev/null | |||
@@ -1,277 +0,0 @@ | |||
1 | // Copyright 2017, 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.md file. | ||
4 | |||
5 | // Package value provides functionality for reflect.Value types. | ||
6 | package value | ||
7 | |||
8 | import ( | ||
9 | "fmt" | ||
10 | "reflect" | ||
11 | "strconv" | ||
12 | "strings" | ||
13 | "unicode" | ||
14 | ) | ||
15 | |||
16 | var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() | ||
17 | |||
18 | // Format formats the value v as a string. | ||
19 | // | ||
20 | // This is similar to fmt.Sprintf("%+v", v) except this: | ||
21 | // * Prints the type unless it can be elided | ||
22 | // * Avoids printing struct fields that are zero | ||
23 | // * Prints a nil-slice as being nil, not empty | ||
24 | // * Prints map entries in deterministic order | ||
25 | func Format(v reflect.Value, conf FormatConfig) string { | ||
26 | conf.printType = true | ||
27 | conf.followPointers = true | ||
28 | conf.realPointers = true | ||
29 | return formatAny(v, conf, nil) | ||
30 | } | ||
31 | |||
32 | type FormatConfig struct { | ||
33 | UseStringer bool // Should the String method be used if available? | ||
34 | printType bool // Should we print the type before the value? | ||
35 | PrintPrimitiveType bool // Should we print the type of primitives? | ||
36 | followPointers bool // Should we recursively follow pointers? | ||
37 | realPointers bool // Should we print the real address of pointers? | ||
38 | } | ||
39 | |||
40 | func formatAny(v reflect.Value, conf FormatConfig, visited map[uintptr]bool) string { | ||
41 | // TODO: Should this be a multi-line printout in certain situations? | ||
42 | |||
43 | if !v.IsValid() { | ||
44 | return "<non-existent>" | ||
45 | } | ||
46 | if conf.UseStringer && v.Type().Implements(stringerIface) && v.CanInterface() { | ||
47 | if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() { | ||
48 | return "<nil>" | ||
49 | } | ||
50 | |||
51 | const stringerPrefix = "s" // Indicates that the String method was used | ||
52 | s := v.Interface().(fmt.Stringer).String() | ||
53 | return stringerPrefix + formatString(s) | ||
54 | } | ||
55 | |||
56 | switch v.Kind() { | ||
57 | case reflect.Bool: | ||
58 | return formatPrimitive(v.Type(), v.Bool(), conf) | ||
59 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
60 | return formatPrimitive(v.Type(), v.Int(), conf) | ||
61 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||
62 | if v.Type().PkgPath() == "" || v.Kind() == reflect.Uintptr { | ||
63 | // Unnamed uints are usually bytes or words, so use hexadecimal. | ||
64 | return formatPrimitive(v.Type(), formatHex(v.Uint()), conf) | ||
65 | } | ||
66 | return formatPrimitive(v.Type(), v.Uint(), conf) | ||
67 | case reflect.Float32, reflect.Float64: | ||
68 | return formatPrimitive(v.Type(), v.Float(), conf) | ||
69 | case reflect.Complex64, reflect.Complex128: | ||
70 | return formatPrimitive(v.Type(), v.Complex(), conf) | ||
71 | case reflect.String: | ||
72 | return formatPrimitive(v.Type(), formatString(v.String()), conf) | ||
73 | case reflect.UnsafePointer, reflect.Chan, reflect.Func: | ||
74 | return formatPointer(v, conf) | ||
75 | case reflect.Ptr: | ||
76 | if v.IsNil() { | ||
77 | if conf.printType { | ||
78 | return fmt.Sprintf("(%v)(nil)", v.Type()) | ||
79 | } | ||
80 | return "<nil>" | ||
81 | } | ||
82 | if visited[v.Pointer()] || !conf.followPointers { | ||
83 | return formatPointer(v, conf) | ||
84 | } | ||
85 | visited = insertPointer(visited, v.Pointer()) | ||
86 | return "&" + formatAny(v.Elem(), conf, visited) | ||
87 | case reflect.Interface: | ||
88 | if v.IsNil() { | ||
89 | if conf.printType { | ||
90 | return fmt.Sprintf("%v(nil)", v.Type()) | ||
91 | } | ||
92 | return "<nil>" | ||
93 | } | ||
94 | return formatAny(v.Elem(), conf, visited) | ||
95 | case reflect.Slice: | ||
96 | if v.IsNil() { | ||
97 | if conf.printType { | ||
98 | return fmt.Sprintf("%v(nil)", v.Type()) | ||
99 | } | ||
100 | return "<nil>" | ||
101 | } | ||
102 | if visited[v.Pointer()] { | ||
103 | return formatPointer(v, conf) | ||
104 | } | ||
105 | visited = insertPointer(visited, v.Pointer()) | ||
106 | fallthrough | ||
107 | case reflect.Array: | ||
108 | var ss []string | ||
109 | subConf := conf | ||
110 | subConf.printType = v.Type().Elem().Kind() == reflect.Interface | ||
111 | for i := 0; i < v.Len(); i++ { | ||
112 | s := formatAny(v.Index(i), subConf, visited) | ||
113 | ss = append(ss, s) | ||
114 | } | ||
115 | s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) | ||
116 | if conf.printType { | ||
117 | return v.Type().String() + s | ||
118 | } | ||
119 | return s | ||
120 | case reflect.Map: | ||
121 | if v.IsNil() { | ||
122 | if conf.printType { | ||
123 | return fmt.Sprintf("%v(nil)", v.Type()) | ||
124 | } | ||
125 | return "<nil>" | ||
126 | } | ||
127 | if visited[v.Pointer()] { | ||
128 | return formatPointer(v, conf) | ||
129 | } | ||
130 | visited = insertPointer(visited, v.Pointer()) | ||
131 | |||
132 | var ss []string | ||
133 | keyConf, valConf := conf, conf | ||
134 | keyConf.printType = v.Type().Key().Kind() == reflect.Interface | ||
135 | keyConf.followPointers = false | ||
136 | valConf.printType = v.Type().Elem().Kind() == reflect.Interface | ||
137 | for _, k := range SortKeys(v.MapKeys()) { | ||
138 | sk := formatAny(k, keyConf, visited) | ||
139 | sv := formatAny(v.MapIndex(k), valConf, visited) | ||
140 | ss = append(ss, fmt.Sprintf("%s: %s", sk, sv)) | ||
141 | } | ||
142 | s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) | ||
143 | if conf.printType { | ||
144 | return v.Type().String() + s | ||
145 | } | ||
146 | return s | ||
147 | case reflect.Struct: | ||
148 | var ss []string | ||
149 | subConf := conf | ||
150 | subConf.printType = true | ||
151 | for i := 0; i < v.NumField(); i++ { | ||
152 | vv := v.Field(i) | ||
153 | if isZero(vv) { | ||
154 | continue // Elide zero value fields | ||
155 | } | ||
156 | name := v.Type().Field(i).Name | ||
157 | subConf.UseStringer = conf.UseStringer | ||
158 | s := formatAny(vv, subConf, visited) | ||
159 | ss = append(ss, fmt.Sprintf("%s: %s", name, s)) | ||
160 | } | ||
161 | s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) | ||
162 | if conf.printType { | ||
163 | return v.Type().String() + s | ||
164 | } | ||
165 | return s | ||
166 | default: | ||
167 | panic(fmt.Sprintf("%v kind not handled", v.Kind())) | ||
168 | } | ||
169 | } | ||
170 | |||
171 | func formatString(s string) string { | ||
172 | // Use quoted string if it the same length as a raw string literal. | ||
173 | // Otherwise, attempt to use the raw string form. | ||
174 | qs := strconv.Quote(s) | ||
175 | if len(qs) == 1+len(s)+1 { | ||
176 | return qs | ||
177 | } | ||
178 | |||
179 | // Disallow newlines to ensure output is a single line. | ||
180 | // Only allow printable runes for readability purposes. | ||
181 | rawInvalid := func(r rune) bool { | ||
182 | return r == '`' || r == '\n' || !unicode.IsPrint(r) | ||
183 | } | ||
184 | if strings.IndexFunc(s, rawInvalid) < 0 { | ||
185 | return "`" + s + "`" | ||
186 | } | ||
187 | return qs | ||
188 | } | ||
189 | |||
190 | func formatPrimitive(t reflect.Type, v interface{}, conf FormatConfig) string { | ||
191 | if conf.printType && (conf.PrintPrimitiveType || t.PkgPath() != "") { | ||
192 | return fmt.Sprintf("%v(%v)", t, v) | ||
193 | } | ||
194 | return fmt.Sprintf("%v", v) | ||
195 | } | ||
196 | |||
197 | func formatPointer(v reflect.Value, conf FormatConfig) string { | ||
198 | p := v.Pointer() | ||
199 | if !conf.realPointers { | ||
200 | p = 0 // For deterministic printing purposes | ||
201 | } | ||
202 | s := formatHex(uint64(p)) | ||
203 | if conf.printType { | ||
204 | return fmt.Sprintf("(%v)(%s)", v.Type(), s) | ||
205 | } | ||
206 | return s | ||
207 | } | ||
208 | |||
209 | func formatHex(u uint64) string { | ||
210 | var f string | ||
211 | switch { | ||
212 | case u <= 0xff: | ||
213 | f = "0x%02x" | ||
214 | case u <= 0xffff: | ||
215 | f = "0x%04x" | ||
216 | case u <= 0xffffff: | ||
217 | f = "0x%06x" | ||
218 | case u <= 0xffffffff: | ||
219 | f = "0x%08x" | ||
220 | case u <= 0xffffffffff: | ||
221 | f = "0x%010x" | ||
222 | case u <= 0xffffffffffff: | ||
223 | f = "0x%012x" | ||
224 | case u <= 0xffffffffffffff: | ||
225 | f = "0x%014x" | ||
226 | case u <= 0xffffffffffffffff: | ||
227 | f = "0x%016x" | ||
228 | } | ||
229 | return fmt.Sprintf(f, u) | ||
230 | } | ||
231 | |||
232 | // insertPointer insert p into m, allocating m if necessary. | ||
233 | func insertPointer(m map[uintptr]bool, p uintptr) map[uintptr]bool { | ||
234 | if m == nil { | ||
235 | m = make(map[uintptr]bool) | ||
236 | } | ||
237 | m[p] = true | ||
238 | return m | ||
239 | } | ||
240 | |||
241 | // isZero reports whether v is the zero value. | ||
242 | // This does not rely on Interface and so can be used on unexported fields. | ||
243 | func isZero(v reflect.Value) bool { | ||
244 | switch v.Kind() { | ||
245 | case reflect.Bool: | ||
246 | return v.Bool() == false | ||
247 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
248 | return v.Int() == 0 | ||
249 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||
250 | return v.Uint() == 0 | ||
251 | case reflect.Float32, reflect.Float64: | ||
252 | return v.Float() == 0 | ||
253 | case reflect.Complex64, reflect.Complex128: | ||
254 | return v.Complex() == 0 | ||
255 | case reflect.String: | ||
256 | return v.String() == "" | ||
257 | case reflect.UnsafePointer: | ||
258 | return v.Pointer() == 0 | ||
259 | case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: | ||
260 | return v.IsNil() | ||
261 | case reflect.Array: | ||
262 | for i := 0; i < v.Len(); i++ { | ||
263 | if !isZero(v.Index(i)) { | ||
264 | return false | ||
265 | } | ||
266 | } | ||
267 | return true | ||
268 | case reflect.Struct: | ||
269 | for i := 0; i < v.NumField(); i++ { | ||
270 | if !isZero(v.Field(i)) { | ||
271 | return false | ||
272 | } | ||
273 | } | ||
274 | return true | ||
275 | } | ||
276 | return false | ||
277 | } | ||