reflect.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // Copyright 2013 Google Inc. All rights reserved.
  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. package pretty
  15. import (
  16. "encoding"
  17. "fmt"
  18. "reflect"
  19. "sort"
  20. )
  21. func isZeroVal(val reflect.Value) bool {
  22. if !val.CanInterface() {
  23. return false
  24. }
  25. z := reflect.Zero(val.Type()).Interface()
  26. return reflect.DeepEqual(val.Interface(), z)
  27. }
  28. // pointerTracker is a helper for tracking pointer chasing to detect cycles.
  29. type pointerTracker struct {
  30. addrs map[uintptr]int // addr[address] = seen count
  31. lastID int
  32. ids map[uintptr]int // ids[address] = id
  33. }
  34. // track tracks following a reference (pointer, slice, map, etc). Every call to
  35. // track should be paired with a call to untrack.
  36. func (p *pointerTracker) track(ptr uintptr) {
  37. if p.addrs == nil {
  38. p.addrs = make(map[uintptr]int)
  39. }
  40. p.addrs[ptr]++
  41. }
  42. // untrack registers that we have backtracked over the reference to the pointer.
  43. func (p *pointerTracker) untrack(ptr uintptr) {
  44. p.addrs[ptr]--
  45. if p.addrs[ptr] == 0 {
  46. delete(p.addrs, ptr)
  47. }
  48. }
  49. // seen returns whether the pointer was previously seen along this path.
  50. func (p *pointerTracker) seen(ptr uintptr) bool {
  51. _, ok := p.addrs[ptr]
  52. return ok
  53. }
  54. // keep allocates an ID for the given address and returns it.
  55. func (p *pointerTracker) keep(ptr uintptr) int {
  56. if p.ids == nil {
  57. p.ids = make(map[uintptr]int)
  58. }
  59. if _, ok := p.ids[ptr]; !ok {
  60. p.lastID++
  61. p.ids[ptr] = p.lastID
  62. }
  63. return p.ids[ptr]
  64. }
  65. // id returns the ID for the given address.
  66. func (p *pointerTracker) id(ptr uintptr) (int, bool) {
  67. if p.ids == nil {
  68. p.ids = make(map[uintptr]int)
  69. }
  70. id, ok := p.ids[ptr]
  71. return id, ok
  72. }
  73. // reflector adds local state to the recursive reflection logic.
  74. type reflector struct {
  75. *Config
  76. *pointerTracker
  77. }
  78. // follow handles following a possiblly-recursive reference to the given value
  79. // from the given ptr address.
  80. func (r *reflector) follow(ptr uintptr, val reflect.Value) node {
  81. if r.pointerTracker == nil {
  82. // Tracking disabled
  83. return r.val2node(val)
  84. }
  85. // If a parent already followed this, emit a reference marker
  86. if r.seen(ptr) {
  87. id := r.keep(ptr)
  88. return ref{id}
  89. }
  90. // Track the pointer we're following while on this recursive branch
  91. r.track(ptr)
  92. defer r.untrack(ptr)
  93. n := r.val2node(val)
  94. // If the recursion used this ptr, wrap it with a target marker
  95. if id, ok := r.id(ptr); ok {
  96. return target{id, n}
  97. }
  98. // Otherwise, return the node unadulterated
  99. return n
  100. }
  101. func (r *reflector) val2node(val reflect.Value) node {
  102. if !val.IsValid() {
  103. return rawVal("nil")
  104. }
  105. if val.CanInterface() {
  106. v := val.Interface()
  107. if formatter, ok := r.Formatter[val.Type()]; ok {
  108. if formatter != nil {
  109. res := reflect.ValueOf(formatter).Call([]reflect.Value{val})
  110. return rawVal(res[0].Interface().(string))
  111. }
  112. } else {
  113. if s, ok := v.(fmt.Stringer); ok && r.PrintStringers {
  114. return stringVal(s.String())
  115. }
  116. if t, ok := v.(encoding.TextMarshaler); ok && r.PrintTextMarshalers {
  117. if raw, err := t.MarshalText(); err == nil { // if NOT an error
  118. return stringVal(string(raw))
  119. }
  120. }
  121. }
  122. }
  123. switch kind := val.Kind(); kind {
  124. case reflect.Ptr:
  125. if val.IsNil() {
  126. return rawVal("nil")
  127. }
  128. return r.follow(val.Pointer(), val.Elem())
  129. case reflect.Interface:
  130. if val.IsNil() {
  131. return rawVal("nil")
  132. }
  133. return r.val2node(val.Elem())
  134. case reflect.String:
  135. return stringVal(val.String())
  136. case reflect.Slice:
  137. n := list{}
  138. length := val.Len()
  139. ptr := val.Pointer()
  140. for i := 0; i < length; i++ {
  141. n = append(n, r.follow(ptr, val.Index(i)))
  142. }
  143. return n
  144. case reflect.Array:
  145. n := list{}
  146. length := val.Len()
  147. for i := 0; i < length; i++ {
  148. n = append(n, r.val2node(val.Index(i)))
  149. }
  150. return n
  151. case reflect.Map:
  152. // Extract the keys and sort them for stable iteration
  153. keys := val.MapKeys()
  154. pairs := make([]mapPair, 0, len(keys))
  155. for _, key := range keys {
  156. pairs = append(pairs, mapPair{
  157. key: new(formatter).compactString(r.val2node(key)), // can't be cyclic
  158. value: val.MapIndex(key),
  159. })
  160. }
  161. sort.Sort(byKey(pairs))
  162. // Process the keys into the final representation
  163. ptr, n := val.Pointer(), keyvals{}
  164. for _, pair := range pairs {
  165. n = append(n, keyval{
  166. key: pair.key,
  167. val: r.follow(ptr, pair.value),
  168. })
  169. }
  170. return n
  171. case reflect.Struct:
  172. n := keyvals{}
  173. typ := val.Type()
  174. fields := typ.NumField()
  175. for i := 0; i < fields; i++ {
  176. sf := typ.Field(i)
  177. if !r.IncludeUnexported && sf.PkgPath != "" {
  178. continue
  179. }
  180. field := val.Field(i)
  181. if r.SkipZeroFields && isZeroVal(field) {
  182. continue
  183. }
  184. n = append(n, keyval{sf.Name, r.val2node(field)})
  185. }
  186. return n
  187. case reflect.Bool:
  188. if val.Bool() {
  189. return rawVal("true")
  190. }
  191. return rawVal("false")
  192. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  193. return rawVal(fmt.Sprintf("%d", val.Int()))
  194. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  195. return rawVal(fmt.Sprintf("%d", val.Uint()))
  196. case reflect.Uintptr:
  197. return rawVal(fmt.Sprintf("0x%X", val.Uint()))
  198. case reflect.Float32, reflect.Float64:
  199. return rawVal(fmt.Sprintf("%v", val.Float()))
  200. case reflect.Complex64, reflect.Complex128:
  201. return rawVal(fmt.Sprintf("%v", val.Complex()))
  202. }
  203. // Fall back to the default %#v if we can
  204. if val.CanInterface() {
  205. return rawVal(fmt.Sprintf("%#v", val.Interface()))
  206. }
  207. return rawVal(val.String())
  208. }
  209. type mapPair struct {
  210. key string
  211. value reflect.Value
  212. }
  213. type byKey []mapPair
  214. func (v byKey) Len() int { return len(v) }
  215. func (v byKey) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
  216. func (v byKey) Less(i, j int) bool { return v[i].key < v[j].key }