render.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. package render
  5. import (
  6. "bytes"
  7. "fmt"
  8. "reflect"
  9. "sort"
  10. "strconv"
  11. )
  12. var builtinTypeMap = map[reflect.Kind]string{
  13. reflect.Bool: "bool",
  14. reflect.Complex128: "complex128",
  15. reflect.Complex64: "complex64",
  16. reflect.Float32: "float32",
  17. reflect.Float64: "float64",
  18. reflect.Int16: "int16",
  19. reflect.Int32: "int32",
  20. reflect.Int64: "int64",
  21. reflect.Int8: "int8",
  22. reflect.Int: "int",
  23. reflect.String: "string",
  24. reflect.Uint16: "uint16",
  25. reflect.Uint32: "uint32",
  26. reflect.Uint64: "uint64",
  27. reflect.Uint8: "uint8",
  28. reflect.Uint: "uint",
  29. reflect.Uintptr: "uintptr",
  30. }
  31. var builtinTypeSet = map[string]struct{}{}
  32. func init() {
  33. for _, v := range builtinTypeMap {
  34. builtinTypeSet[v] = struct{}{}
  35. }
  36. }
  37. var typeOfString = reflect.TypeOf("")
  38. var typeOfInt = reflect.TypeOf(int(1))
  39. var typeOfUint = reflect.TypeOf(uint(1))
  40. var typeOfFloat = reflect.TypeOf(10.1)
  41. // Render converts a structure to a string representation. Unline the "%#v"
  42. // format string, this resolves pointer types' contents in structs, maps, and
  43. // slices/arrays and prints their field values.
  44. func Render(v interface{}) string {
  45. buf := bytes.Buffer{}
  46. s := (*traverseState)(nil)
  47. s.render(&buf, 0, reflect.ValueOf(v), false)
  48. return buf.String()
  49. }
  50. // renderPointer is called to render a pointer value.
  51. //
  52. // This is overridable so that the test suite can have deterministic pointer
  53. // values in its expectations.
  54. var renderPointer = func(buf *bytes.Buffer, p uintptr) {
  55. fmt.Fprintf(buf, "0x%016x", p)
  56. }
  57. // traverseState is used to note and avoid recursion as struct members are being
  58. // traversed.
  59. //
  60. // traverseState is allowed to be nil. Specifically, the root state is nil.
  61. type traverseState struct {
  62. parent *traverseState
  63. ptr uintptr
  64. }
  65. func (s *traverseState) forkFor(ptr uintptr) *traverseState {
  66. for cur := s; cur != nil; cur = cur.parent {
  67. if ptr == cur.ptr {
  68. return nil
  69. }
  70. }
  71. fs := &traverseState{
  72. parent: s,
  73. ptr: ptr,
  74. }
  75. return fs
  76. }
  77. func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value, implicit bool) {
  78. if v.Kind() == reflect.Invalid {
  79. buf.WriteString("nil")
  80. return
  81. }
  82. vt := v.Type()
  83. // If the type being rendered is a potentially recursive type (a type that
  84. // can contain itself as a member), we need to avoid recursion.
  85. //
  86. // If we've already seen this type before, mark that this is the case and
  87. // write a recursion placeholder instead of actually rendering it.
  88. //
  89. // If we haven't seen it before, fork our `seen` tracking so any higher-up
  90. // renderers will also render it at least once, then mark that we've seen it
  91. // to avoid recursing on lower layers.
  92. pe := uintptr(0)
  93. vk := vt.Kind()
  94. switch vk {
  95. case reflect.Ptr:
  96. // Since structs and arrays aren't pointers, they can't directly be
  97. // recursed, but they can contain pointers to themselves. Record their
  98. // pointer to avoid this.
  99. switch v.Elem().Kind() {
  100. case reflect.Struct, reflect.Array:
  101. pe = v.Pointer()
  102. }
  103. case reflect.Slice, reflect.Map:
  104. pe = v.Pointer()
  105. }
  106. if pe != 0 {
  107. s = s.forkFor(pe)
  108. if s == nil {
  109. buf.WriteString("<REC(")
  110. if !implicit {
  111. writeType(buf, ptrs, vt)
  112. }
  113. buf.WriteString(")>")
  114. return
  115. }
  116. }
  117. isAnon := func(t reflect.Type) bool {
  118. if t.Name() != "" {
  119. if _, ok := builtinTypeSet[t.Name()]; !ok {
  120. return false
  121. }
  122. }
  123. return t.Kind() != reflect.Interface
  124. }
  125. switch vk {
  126. case reflect.Struct:
  127. if !implicit {
  128. writeType(buf, ptrs, vt)
  129. }
  130. structAnon := vt.Name() == ""
  131. buf.WriteRune('{')
  132. for i := 0; i < vt.NumField(); i++ {
  133. if i > 0 {
  134. buf.WriteString(", ")
  135. }
  136. anon := structAnon && isAnon(vt.Field(i).Type)
  137. if !anon {
  138. buf.WriteString(vt.Field(i).Name)
  139. buf.WriteRune(':')
  140. }
  141. s.render(buf, 0, v.Field(i), anon)
  142. }
  143. buf.WriteRune('}')
  144. case reflect.Slice:
  145. if v.IsNil() {
  146. if !implicit {
  147. writeType(buf, ptrs, vt)
  148. buf.WriteString("(nil)")
  149. } else {
  150. buf.WriteString("nil")
  151. }
  152. return
  153. }
  154. fallthrough
  155. case reflect.Array:
  156. if !implicit {
  157. writeType(buf, ptrs, vt)
  158. }
  159. anon := vt.Name() == "" && isAnon(vt.Elem())
  160. buf.WriteString("{")
  161. for i := 0; i < v.Len(); i++ {
  162. if i > 0 {
  163. buf.WriteString(", ")
  164. }
  165. s.render(buf, 0, v.Index(i), anon)
  166. }
  167. buf.WriteRune('}')
  168. case reflect.Map:
  169. if !implicit {
  170. writeType(buf, ptrs, vt)
  171. }
  172. if v.IsNil() {
  173. buf.WriteString("(nil)")
  174. } else {
  175. buf.WriteString("{")
  176. mkeys := v.MapKeys()
  177. tryAndSortMapKeys(vt, mkeys)
  178. kt := vt.Key()
  179. keyAnon := typeOfString.ConvertibleTo(kt) || typeOfInt.ConvertibleTo(kt) || typeOfUint.ConvertibleTo(kt) || typeOfFloat.ConvertibleTo(kt)
  180. valAnon := vt.Name() == "" && isAnon(vt.Elem())
  181. for i, mk := range mkeys {
  182. if i > 0 {
  183. buf.WriteString(", ")
  184. }
  185. s.render(buf, 0, mk, keyAnon)
  186. buf.WriteString(":")
  187. s.render(buf, 0, v.MapIndex(mk), valAnon)
  188. }
  189. buf.WriteRune('}')
  190. }
  191. case reflect.Ptr:
  192. ptrs++
  193. fallthrough
  194. case reflect.Interface:
  195. if v.IsNil() {
  196. writeType(buf, ptrs, v.Type())
  197. buf.WriteString("(nil)")
  198. } else {
  199. s.render(buf, ptrs, v.Elem(), false)
  200. }
  201. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  202. writeType(buf, ptrs, vt)
  203. buf.WriteRune('(')
  204. renderPointer(buf, v.Pointer())
  205. buf.WriteRune(')')
  206. default:
  207. tstr := vt.String()
  208. implicit = implicit || (ptrs == 0 && builtinTypeMap[vk] == tstr)
  209. if !implicit {
  210. writeType(buf, ptrs, vt)
  211. buf.WriteRune('(')
  212. }
  213. switch vk {
  214. case reflect.String:
  215. fmt.Fprintf(buf, "%q", v.String())
  216. case reflect.Bool:
  217. fmt.Fprintf(buf, "%v", v.Bool())
  218. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  219. fmt.Fprintf(buf, "%d", v.Int())
  220. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  221. fmt.Fprintf(buf, "%d", v.Uint())
  222. case reflect.Float32, reflect.Float64:
  223. fmt.Fprintf(buf, "%g", v.Float())
  224. case reflect.Complex64, reflect.Complex128:
  225. fmt.Fprintf(buf, "%g", v.Complex())
  226. }
  227. if !implicit {
  228. buf.WriteRune(')')
  229. }
  230. }
  231. }
  232. func writeType(buf *bytes.Buffer, ptrs int, t reflect.Type) {
  233. parens := ptrs > 0
  234. switch t.Kind() {
  235. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  236. parens = true
  237. }
  238. if parens {
  239. buf.WriteRune('(')
  240. for i := 0; i < ptrs; i++ {
  241. buf.WriteRune('*')
  242. }
  243. }
  244. switch t.Kind() {
  245. case reflect.Ptr:
  246. if ptrs == 0 {
  247. // This pointer was referenced from within writeType (e.g., as part of
  248. // rendering a list), and so hasn't had its pointer asterisk accounted
  249. // for.
  250. buf.WriteRune('*')
  251. }
  252. writeType(buf, 0, t.Elem())
  253. case reflect.Interface:
  254. if n := t.Name(); n != "" {
  255. buf.WriteString(t.String())
  256. } else {
  257. buf.WriteString("interface{}")
  258. }
  259. case reflect.Array:
  260. buf.WriteRune('[')
  261. buf.WriteString(strconv.FormatInt(int64(t.Len()), 10))
  262. buf.WriteRune(']')
  263. writeType(buf, 0, t.Elem())
  264. case reflect.Slice:
  265. if t == reflect.SliceOf(t.Elem()) {
  266. buf.WriteString("[]")
  267. writeType(buf, 0, t.Elem())
  268. } else {
  269. // Custom slice type, use type name.
  270. buf.WriteString(t.String())
  271. }
  272. case reflect.Map:
  273. if t == reflect.MapOf(t.Key(), t.Elem()) {
  274. buf.WriteString("map[")
  275. writeType(buf, 0, t.Key())
  276. buf.WriteRune(']')
  277. writeType(buf, 0, t.Elem())
  278. } else {
  279. // Custom map type, use type name.
  280. buf.WriteString(t.String())
  281. }
  282. default:
  283. buf.WriteString(t.String())
  284. }
  285. if parens {
  286. buf.WriteRune(')')
  287. }
  288. }
  289. type cmpFn func(a, b reflect.Value) int
  290. type sortableValueSlice struct {
  291. cmp cmpFn
  292. elements []reflect.Value
  293. }
  294. func (s sortableValueSlice) Len() int {
  295. return len(s.elements)
  296. }
  297. func (s sortableValueSlice) Less(i, j int) bool {
  298. return s.cmp(s.elements[i], s.elements[j]) < 0
  299. }
  300. func (s sortableValueSlice) Swap(i, j int) {
  301. s.elements[i], s.elements[j] = s.elements[j], s.elements[i]
  302. }
  303. // cmpForType returns a cmpFn which sorts the data for some type t in the same
  304. // order that a go-native map key is compared for equality.
  305. func cmpForType(t reflect.Type) cmpFn {
  306. switch t.Kind() {
  307. case reflect.String:
  308. return func(av, bv reflect.Value) int {
  309. a, b := av.String(), bv.String()
  310. if a < b {
  311. return -1
  312. } else if a > b {
  313. return 1
  314. }
  315. return 0
  316. }
  317. case reflect.Bool:
  318. return func(av, bv reflect.Value) int {
  319. a, b := av.Bool(), bv.Bool()
  320. if !a && b {
  321. return -1
  322. } else if a && !b {
  323. return 1
  324. }
  325. return 0
  326. }
  327. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  328. return func(av, bv reflect.Value) int {
  329. a, b := av.Int(), bv.Int()
  330. if a < b {
  331. return -1
  332. } else if a > b {
  333. return 1
  334. }
  335. return 0
  336. }
  337. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
  338. reflect.Uint64, reflect.Uintptr, reflect.UnsafePointer:
  339. return func(av, bv reflect.Value) int {
  340. a, b := av.Uint(), bv.Uint()
  341. if a < b {
  342. return -1
  343. } else if a > b {
  344. return 1
  345. }
  346. return 0
  347. }
  348. case reflect.Float32, reflect.Float64:
  349. return func(av, bv reflect.Value) int {
  350. a, b := av.Float(), bv.Float()
  351. if a < b {
  352. return -1
  353. } else if a > b {
  354. return 1
  355. }
  356. return 0
  357. }
  358. case reflect.Interface:
  359. return func(av, bv reflect.Value) int {
  360. a, b := av.InterfaceData(), bv.InterfaceData()
  361. if a[0] < b[0] {
  362. return -1
  363. } else if a[0] > b[0] {
  364. return 1
  365. }
  366. if a[1] < b[1] {
  367. return -1
  368. } else if a[1] > b[1] {
  369. return 1
  370. }
  371. return 0
  372. }
  373. case reflect.Complex64, reflect.Complex128:
  374. return func(av, bv reflect.Value) int {
  375. a, b := av.Complex(), bv.Complex()
  376. if real(a) < real(b) {
  377. return -1
  378. } else if real(a) > real(b) {
  379. return 1
  380. }
  381. if imag(a) < imag(b) {
  382. return -1
  383. } else if imag(a) > imag(b) {
  384. return 1
  385. }
  386. return 0
  387. }
  388. case reflect.Ptr, reflect.Chan:
  389. return func(av, bv reflect.Value) int {
  390. a, b := av.Pointer(), bv.Pointer()
  391. if a < b {
  392. return -1
  393. } else if a > b {
  394. return 1
  395. }
  396. return 0
  397. }
  398. case reflect.Struct:
  399. cmpLst := make([]cmpFn, t.NumField())
  400. for i := range cmpLst {
  401. cmpLst[i] = cmpForType(t.Field(i).Type)
  402. }
  403. return func(a, b reflect.Value) int {
  404. for i, cmp := range cmpLst {
  405. if rslt := cmp(a.Field(i), b.Field(i)); rslt != 0 {
  406. return rslt
  407. }
  408. }
  409. return 0
  410. }
  411. }
  412. return nil
  413. }
  414. func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) {
  415. if cmp := cmpForType(mt.Key()); cmp != nil {
  416. sort.Sort(sortableValueSlice{cmp, k})
  417. }
  418. }