render.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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. buf.WriteRune('{')
  131. if rendered, ok := renderTime(v); ok {
  132. buf.WriteString(rendered)
  133. } else {
  134. structAnon := vt.Name() == ""
  135. for i := 0; i < vt.NumField(); i++ {
  136. if i > 0 {
  137. buf.WriteString(", ")
  138. }
  139. anon := structAnon && isAnon(vt.Field(i).Type)
  140. if !anon {
  141. buf.WriteString(vt.Field(i).Name)
  142. buf.WriteRune(':')
  143. }
  144. s.render(buf, 0, v.Field(i), anon)
  145. }
  146. }
  147. buf.WriteRune('}')
  148. case reflect.Slice:
  149. if v.IsNil() {
  150. if !implicit {
  151. writeType(buf, ptrs, vt)
  152. buf.WriteString("(nil)")
  153. } else {
  154. buf.WriteString("nil")
  155. }
  156. return
  157. }
  158. fallthrough
  159. case reflect.Array:
  160. if !implicit {
  161. writeType(buf, ptrs, vt)
  162. }
  163. anon := vt.Name() == "" && isAnon(vt.Elem())
  164. buf.WriteString("{")
  165. for i := 0; i < v.Len(); i++ {
  166. if i > 0 {
  167. buf.WriteString(", ")
  168. }
  169. s.render(buf, 0, v.Index(i), anon)
  170. }
  171. buf.WriteRune('}')
  172. case reflect.Map:
  173. if !implicit {
  174. writeType(buf, ptrs, vt)
  175. }
  176. if v.IsNil() {
  177. buf.WriteString("(nil)")
  178. } else {
  179. buf.WriteString("{")
  180. mkeys := v.MapKeys()
  181. tryAndSortMapKeys(vt, mkeys)
  182. kt := vt.Key()
  183. keyAnon := typeOfString.ConvertibleTo(kt) || typeOfInt.ConvertibleTo(kt) || typeOfUint.ConvertibleTo(kt) || typeOfFloat.ConvertibleTo(kt)
  184. valAnon := vt.Name() == "" && isAnon(vt.Elem())
  185. for i, mk := range mkeys {
  186. if i > 0 {
  187. buf.WriteString(", ")
  188. }
  189. s.render(buf, 0, mk, keyAnon)
  190. buf.WriteString(":")
  191. s.render(buf, 0, v.MapIndex(mk), valAnon)
  192. }
  193. buf.WriteRune('}')
  194. }
  195. case reflect.Ptr:
  196. ptrs++
  197. fallthrough
  198. case reflect.Interface:
  199. if v.IsNil() {
  200. writeType(buf, ptrs, v.Type())
  201. buf.WriteString("(nil)")
  202. } else {
  203. s.render(buf, ptrs, v.Elem(), false)
  204. }
  205. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  206. writeType(buf, ptrs, vt)
  207. buf.WriteRune('(')
  208. renderPointer(buf, v.Pointer())
  209. buf.WriteRune(')')
  210. default:
  211. tstr := vt.String()
  212. implicit = implicit || (ptrs == 0 && builtinTypeMap[vk] == tstr)
  213. if !implicit {
  214. writeType(buf, ptrs, vt)
  215. buf.WriteRune('(')
  216. }
  217. switch vk {
  218. case reflect.String:
  219. fmt.Fprintf(buf, "%q", v.String())
  220. case reflect.Bool:
  221. fmt.Fprintf(buf, "%v", v.Bool())
  222. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  223. fmt.Fprintf(buf, "%d", v.Int())
  224. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  225. fmt.Fprintf(buf, "%d", v.Uint())
  226. case reflect.Float32, reflect.Float64:
  227. fmt.Fprintf(buf, "%g", v.Float())
  228. case reflect.Complex64, reflect.Complex128:
  229. fmt.Fprintf(buf, "%g", v.Complex())
  230. }
  231. if !implicit {
  232. buf.WriteRune(')')
  233. }
  234. }
  235. }
  236. func writeType(buf *bytes.Buffer, ptrs int, t reflect.Type) {
  237. parens := ptrs > 0
  238. switch t.Kind() {
  239. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  240. parens = true
  241. }
  242. if parens {
  243. buf.WriteRune('(')
  244. for i := 0; i < ptrs; i++ {
  245. buf.WriteRune('*')
  246. }
  247. }
  248. switch t.Kind() {
  249. case reflect.Ptr:
  250. if ptrs == 0 {
  251. // This pointer was referenced from within writeType (e.g., as part of
  252. // rendering a list), and so hasn't had its pointer asterisk accounted
  253. // for.
  254. buf.WriteRune('*')
  255. }
  256. writeType(buf, 0, t.Elem())
  257. case reflect.Interface:
  258. if n := t.Name(); n != "" {
  259. buf.WriteString(t.String())
  260. } else {
  261. buf.WriteString("interface{}")
  262. }
  263. case reflect.Array:
  264. buf.WriteRune('[')
  265. buf.WriteString(strconv.FormatInt(int64(t.Len()), 10))
  266. buf.WriteRune(']')
  267. writeType(buf, 0, t.Elem())
  268. case reflect.Slice:
  269. if t == reflect.SliceOf(t.Elem()) {
  270. buf.WriteString("[]")
  271. writeType(buf, 0, t.Elem())
  272. } else {
  273. // Custom slice type, use type name.
  274. buf.WriteString(t.String())
  275. }
  276. case reflect.Map:
  277. if t == reflect.MapOf(t.Key(), t.Elem()) {
  278. buf.WriteString("map[")
  279. writeType(buf, 0, t.Key())
  280. buf.WriteRune(']')
  281. writeType(buf, 0, t.Elem())
  282. } else {
  283. // Custom map type, use type name.
  284. buf.WriteString(t.String())
  285. }
  286. default:
  287. buf.WriteString(t.String())
  288. }
  289. if parens {
  290. buf.WriteRune(')')
  291. }
  292. }
  293. type cmpFn func(a, b reflect.Value) int
  294. type sortableValueSlice struct {
  295. cmp cmpFn
  296. elements []reflect.Value
  297. }
  298. func (s sortableValueSlice) Len() int {
  299. return len(s.elements)
  300. }
  301. func (s sortableValueSlice) Less(i, j int) bool {
  302. return s.cmp(s.elements[i], s.elements[j]) < 0
  303. }
  304. func (s sortableValueSlice) Swap(i, j int) {
  305. s.elements[i], s.elements[j] = s.elements[j], s.elements[i]
  306. }
  307. // cmpForType returns a cmpFn which sorts the data for some type t in the same
  308. // order that a go-native map key is compared for equality.
  309. func cmpForType(t reflect.Type) cmpFn {
  310. switch t.Kind() {
  311. case reflect.String:
  312. return func(av, bv reflect.Value) int {
  313. a, b := av.String(), bv.String()
  314. if a < b {
  315. return -1
  316. } else if a > b {
  317. return 1
  318. }
  319. return 0
  320. }
  321. case reflect.Bool:
  322. return func(av, bv reflect.Value) int {
  323. a, b := av.Bool(), bv.Bool()
  324. if !a && b {
  325. return -1
  326. } else if a && !b {
  327. return 1
  328. }
  329. return 0
  330. }
  331. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  332. return func(av, bv reflect.Value) int {
  333. a, b := av.Int(), bv.Int()
  334. if a < b {
  335. return -1
  336. } else if a > b {
  337. return 1
  338. }
  339. return 0
  340. }
  341. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
  342. reflect.Uint64, reflect.Uintptr, reflect.UnsafePointer:
  343. return func(av, bv reflect.Value) int {
  344. a, b := av.Uint(), bv.Uint()
  345. if a < b {
  346. return -1
  347. } else if a > b {
  348. return 1
  349. }
  350. return 0
  351. }
  352. case reflect.Float32, reflect.Float64:
  353. return func(av, bv reflect.Value) int {
  354. a, b := av.Float(), bv.Float()
  355. if a < b {
  356. return -1
  357. } else if a > b {
  358. return 1
  359. }
  360. return 0
  361. }
  362. case reflect.Interface:
  363. return func(av, bv reflect.Value) int {
  364. a, b := av.InterfaceData(), bv.InterfaceData()
  365. if a[0] < b[0] {
  366. return -1
  367. } else if a[0] > b[0] {
  368. return 1
  369. }
  370. if a[1] < b[1] {
  371. return -1
  372. } else if a[1] > b[1] {
  373. return 1
  374. }
  375. return 0
  376. }
  377. case reflect.Complex64, reflect.Complex128:
  378. return func(av, bv reflect.Value) int {
  379. a, b := av.Complex(), bv.Complex()
  380. if real(a) < real(b) {
  381. return -1
  382. } else if real(a) > real(b) {
  383. return 1
  384. }
  385. if imag(a) < imag(b) {
  386. return -1
  387. } else if imag(a) > imag(b) {
  388. return 1
  389. }
  390. return 0
  391. }
  392. case reflect.Ptr, reflect.Chan:
  393. return func(av, bv reflect.Value) int {
  394. a, b := av.Pointer(), bv.Pointer()
  395. if a < b {
  396. return -1
  397. } else if a > b {
  398. return 1
  399. }
  400. return 0
  401. }
  402. case reflect.Struct:
  403. cmpLst := make([]cmpFn, t.NumField())
  404. for i := range cmpLst {
  405. cmpLst[i] = cmpForType(t.Field(i).Type)
  406. }
  407. return func(a, b reflect.Value) int {
  408. for i, cmp := range cmpLst {
  409. if rslt := cmp(a.Field(i), b.Field(i)); rslt != 0 {
  410. return rslt
  411. }
  412. }
  413. return 0
  414. }
  415. }
  416. return nil
  417. }
  418. func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) {
  419. if cmp := cmpForType(mt.Key()); cmp != nil {
  420. sort.Sort(sortableValueSlice{cmp, k})
  421. }
  422. }