render.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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 implicitTypeMap = map[reflect.Kind]string{
  13. reflect.Bool: "bool",
  14. reflect.String: "string",
  15. reflect.Int: "int",
  16. reflect.Int8: "int8",
  17. reflect.Int16: "int16",
  18. reflect.Int32: "int32",
  19. reflect.Int64: "int64",
  20. reflect.Uint: "uint",
  21. reflect.Uint8: "uint8",
  22. reflect.Uint16: "uint16",
  23. reflect.Uint32: "uint32",
  24. reflect.Uint64: "uint64",
  25. reflect.Float32: "float32",
  26. reflect.Float64: "float64",
  27. reflect.Complex64: "complex64",
  28. reflect.Complex128: "complex128",
  29. }
  30. // Render converts a structure to a string representation. Unline the "%#v"
  31. // format string, this resolves pointer types' contents in structs, maps, and
  32. // slices/arrays and prints their field values.
  33. func Render(v interface{}) string {
  34. buf := bytes.Buffer{}
  35. s := (*traverseState)(nil)
  36. s.render(&buf, 0, reflect.ValueOf(v))
  37. return buf.String()
  38. }
  39. // renderPointer is called to render a pointer value.
  40. //
  41. // This is overridable so that the test suite can have deterministic pointer
  42. // values in its expectations.
  43. var renderPointer = func(buf *bytes.Buffer, p uintptr) {
  44. fmt.Fprintf(buf, "0x%016x", p)
  45. }
  46. // traverseState is used to note and avoid recursion as struct members are being
  47. // traversed.
  48. //
  49. // traverseState is allowed to be nil. Specifically, the root state is nil.
  50. type traverseState struct {
  51. parent *traverseState
  52. ptr uintptr
  53. }
  54. func (s *traverseState) forkFor(ptr uintptr) *traverseState {
  55. for cur := s; cur != nil; cur = cur.parent {
  56. if ptr == cur.ptr {
  57. return nil
  58. }
  59. }
  60. fs := &traverseState{
  61. parent: s,
  62. ptr: ptr,
  63. }
  64. return fs
  65. }
  66. func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
  67. if v.Kind() == reflect.Invalid {
  68. buf.WriteString("nil")
  69. return
  70. }
  71. vt := v.Type()
  72. // If the type being rendered is a potentially recursive type (a type that
  73. // can contain itself as a member), we need to avoid recursion.
  74. //
  75. // If we've already seen this type before, mark that this is the case and
  76. // write a recursion placeholder instead of actually rendering it.
  77. //
  78. // If we haven't seen it before, fork our `seen` tracking so any higher-up
  79. // renderers will also render it at least once, then mark that we've seen it
  80. // to avoid recursing on lower layers.
  81. pe := uintptr(0)
  82. vk := vt.Kind()
  83. switch vk {
  84. case reflect.Ptr:
  85. // Since structs and arrays aren't pointers, they can't directly be
  86. // recursed, but they can contain pointers to themselves. Record their
  87. // pointer to avoid this.
  88. switch v.Elem().Kind() {
  89. case reflect.Struct, reflect.Array:
  90. pe = v.Pointer()
  91. }
  92. case reflect.Slice, reflect.Map:
  93. pe = v.Pointer()
  94. }
  95. if pe != 0 {
  96. s = s.forkFor(pe)
  97. if s == nil {
  98. buf.WriteString("<REC(")
  99. writeType(buf, ptrs, vt)
  100. buf.WriteString(")>")
  101. return
  102. }
  103. }
  104. switch vk {
  105. case reflect.Struct:
  106. writeType(buf, ptrs, vt)
  107. buf.WriteRune('{')
  108. for i := 0; i < vt.NumField(); i++ {
  109. if i > 0 {
  110. buf.WriteString(", ")
  111. }
  112. buf.WriteString(vt.Field(i).Name)
  113. buf.WriteRune(':')
  114. s.render(buf, 0, v.Field(i))
  115. }
  116. buf.WriteRune('}')
  117. case reflect.Slice:
  118. if v.IsNil() {
  119. writeType(buf, ptrs, vt)
  120. buf.WriteString("(nil)")
  121. return
  122. }
  123. fallthrough
  124. case reflect.Array:
  125. writeType(buf, ptrs, vt)
  126. buf.WriteString("{")
  127. for i := 0; i < v.Len(); i++ {
  128. if i > 0 {
  129. buf.WriteString(", ")
  130. }
  131. s.render(buf, 0, v.Index(i))
  132. }
  133. buf.WriteRune('}')
  134. case reflect.Map:
  135. writeType(buf, ptrs, vt)
  136. if v.IsNil() {
  137. buf.WriteString("(nil)")
  138. } else {
  139. buf.WriteString("{")
  140. mkeys := v.MapKeys()
  141. tryAndSortMapKeys(vt, mkeys)
  142. for i, mk := range mkeys {
  143. if i > 0 {
  144. buf.WriteString(", ")
  145. }
  146. s.render(buf, 0, mk)
  147. buf.WriteString(":")
  148. s.render(buf, 0, v.MapIndex(mk))
  149. }
  150. buf.WriteRune('}')
  151. }
  152. case reflect.Ptr:
  153. ptrs++
  154. fallthrough
  155. case reflect.Interface:
  156. if v.IsNil() {
  157. writeType(buf, ptrs, v.Type())
  158. buf.WriteRune('(')
  159. fmt.Fprint(buf, "nil")
  160. buf.WriteRune(')')
  161. } else {
  162. s.render(buf, ptrs, v.Elem())
  163. }
  164. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  165. writeType(buf, ptrs, vt)
  166. buf.WriteRune('(')
  167. renderPointer(buf, v.Pointer())
  168. buf.WriteRune(')')
  169. default:
  170. tstr := vt.String()
  171. implicit := ptrs == 0 && implicitTypeMap[vk] == tstr
  172. if !implicit {
  173. writeType(buf, ptrs, vt)
  174. buf.WriteRune('(')
  175. }
  176. switch vk {
  177. case reflect.String:
  178. fmt.Fprintf(buf, "%q", v.String())
  179. case reflect.Bool:
  180. fmt.Fprintf(buf, "%v", v.Bool())
  181. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  182. fmt.Fprintf(buf, "%d", v.Int())
  183. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  184. fmt.Fprintf(buf, "%d", v.Uint())
  185. case reflect.Float32, reflect.Float64:
  186. fmt.Fprintf(buf, "%g", v.Float())
  187. case reflect.Complex64, reflect.Complex128:
  188. fmt.Fprintf(buf, "%g", v.Complex())
  189. }
  190. if !implicit {
  191. buf.WriteRune(')')
  192. }
  193. }
  194. }
  195. func writeType(buf *bytes.Buffer, ptrs int, t reflect.Type) {
  196. parens := ptrs > 0
  197. switch t.Kind() {
  198. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  199. parens = true
  200. }
  201. if parens {
  202. buf.WriteRune('(')
  203. for i := 0; i < ptrs; i++ {
  204. buf.WriteRune('*')
  205. }
  206. }
  207. switch t.Kind() {
  208. case reflect.Ptr:
  209. if ptrs == 0 {
  210. // This pointer was referenced from within writeType (e.g., as part of
  211. // rendering a list), and so hasn't had its pointer asterisk accounted
  212. // for.
  213. buf.WriteRune('*')
  214. }
  215. writeType(buf, 0, t.Elem())
  216. case reflect.Interface:
  217. if n := t.Name(); n != "" {
  218. buf.WriteString(t.String())
  219. } else {
  220. buf.WriteString("interface{}")
  221. }
  222. case reflect.Array:
  223. buf.WriteRune('[')
  224. buf.WriteString(strconv.FormatInt(int64(t.Len()), 10))
  225. buf.WriteRune(']')
  226. writeType(buf, 0, t.Elem())
  227. case reflect.Slice:
  228. if t == reflect.SliceOf(t.Elem()) {
  229. buf.WriteString("[]")
  230. writeType(buf, 0, t.Elem())
  231. } else {
  232. // Custom slice type, use type name.
  233. buf.WriteString(t.String())
  234. }
  235. case reflect.Map:
  236. if t == reflect.MapOf(t.Key(), t.Elem()) {
  237. buf.WriteString("map[")
  238. writeType(buf, 0, t.Key())
  239. buf.WriteRune(']')
  240. writeType(buf, 0, t.Elem())
  241. } else {
  242. // Custom map type, use type name.
  243. buf.WriteString(t.String())
  244. }
  245. default:
  246. buf.WriteString(t.String())
  247. }
  248. if parens {
  249. buf.WriteRune(')')
  250. }
  251. }
  252. type sortableValueSlice struct {
  253. kind reflect.Kind
  254. elements []reflect.Value
  255. }
  256. func (s *sortableValueSlice) Len() int {
  257. return len(s.elements)
  258. }
  259. func (s *sortableValueSlice) Less(i, j int) bool {
  260. switch s.kind {
  261. case reflect.String:
  262. return s.elements[i].String() < s.elements[j].String()
  263. case reflect.Int:
  264. return s.elements[i].Int() < s.elements[j].Int()
  265. default:
  266. panic(fmt.Errorf("unsupported sort kind: %s", s.kind))
  267. }
  268. }
  269. func (s *sortableValueSlice) Swap(i, j int) {
  270. s.elements[i], s.elements[j] = s.elements[j], s.elements[i]
  271. }
  272. func tryAndSortMapKeys(mt reflect.Type, k []reflect.Value) {
  273. // Try our stock sortable values.
  274. switch mt.Key().Kind() {
  275. case reflect.String, reflect.Int:
  276. vs := &sortableValueSlice{
  277. kind: mt.Key().Kind(),
  278. elements: k,
  279. }
  280. sort.Sort(vs)
  281. }
  282. }