reflect.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package hero
  2. import (
  3. "net"
  4. "reflect"
  5. "github.com/kataras/iris/v12/context"
  6. )
  7. func valueOf(v interface{}) reflect.Value {
  8. if val, ok := v.(reflect.Value); ok {
  9. // check if it's already a reflect.Value.
  10. return val
  11. }
  12. return reflect.ValueOf(v)
  13. }
  14. // indirectType returns the value of a pointer-type "typ".
  15. // If "typ" is a pointer, array, chan, map or slice it returns its Elem,
  16. // otherwise returns the "typ" as it is.
  17. func indirectType(typ reflect.Type) reflect.Type {
  18. switch typ.Kind() {
  19. case reflect.Ptr, reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
  20. return typ.Elem()
  21. }
  22. return typ
  23. }
  24. func goodVal(v reflect.Value) bool {
  25. switch v.Kind() {
  26. case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
  27. if v.IsNil() {
  28. return false
  29. }
  30. }
  31. return v.IsValid()
  32. }
  33. func isFunc(kindable interface{ Kind() reflect.Kind }) bool {
  34. return kindable.Kind() == reflect.Func
  35. }
  36. func isStructValue(v reflect.Value) bool {
  37. return indirectType(v.Type()).Kind() == reflect.Struct
  38. }
  39. // isBuiltin reports whether a reflect.Value is a builtin type
  40. func isBuiltinValue(v reflect.Value) bool {
  41. switch v.Type().Kind() {
  42. case reflect.Bool,
  43. reflect.Int,
  44. reflect.Int8,
  45. reflect.Int16,
  46. reflect.Int32,
  47. reflect.Int64,
  48. reflect.Uint,
  49. reflect.Uint8,
  50. reflect.Uint16,
  51. reflect.Uint32,
  52. reflect.Uint64,
  53. reflect.Float32,
  54. reflect.Float64,
  55. reflect.Complex64,
  56. reflect.Complex128,
  57. reflect.Array,
  58. reflect.Chan,
  59. reflect.Map,
  60. reflect.Slice,
  61. reflect.String:
  62. return true
  63. default:
  64. return false
  65. }
  66. }
  67. var (
  68. inputTyp = reflect.TypeOf((*Input)(nil))
  69. errTyp = reflect.TypeOf((*error)(nil)).Elem()
  70. ipTyp = reflect.TypeOf(net.IP{})
  71. )
  72. // isError returns true if "typ" is type of `error`.
  73. func isError(typ reflect.Type) bool {
  74. return typ.Implements(errTyp)
  75. }
  76. func toError(v reflect.Value) error {
  77. if v.IsNil() {
  78. return nil
  79. }
  80. return v.Interface().(error)
  81. }
  82. var contextType = reflect.TypeOf((*context.Context)(nil))
  83. // isContext returns true if the "typ" is a type of Context.
  84. func isContext(typ reflect.Type) bool {
  85. return typ == contextType
  86. }
  87. var errorHandlerTyp = reflect.TypeOf((*ErrorHandler)(nil)).Elem()
  88. func isErrorHandler(typ reflect.Type) bool {
  89. return typ.Implements(errorHandlerTyp)
  90. }
  91. var emptyValue reflect.Value
  92. func equalTypes(binding reflect.Type, input reflect.Type) bool {
  93. if binding == input {
  94. return true
  95. }
  96. // fmt.Printf("got: %s expected: %s\n", got.String(), expected.String())
  97. // if accepts an interface, check if the given "got" type does
  98. // implement this "expected" user handler's input argument.
  99. if input.Kind() == reflect.Interface {
  100. // fmt.Printf("expected interface = %s and got to set on the arg is: %s\n", binding.String(), input.String())
  101. // return input.Implements(binding)
  102. return binding.AssignableTo(input)
  103. }
  104. // dependency: func(...) interface{} { return "string" }
  105. // expected input: string.
  106. if binding.Kind() == reflect.Interface {
  107. return input.AssignableTo(binding)
  108. }
  109. return false
  110. }
  111. func structFieldIgnored(f reflect.StructField) bool {
  112. if !f.Anonymous {
  113. return true // if not anonymous(embedded), ignore it.
  114. }
  115. if s := f.Tag.Get("ignore"); s == "true" {
  116. return true
  117. }
  118. if s := f.Tag.Get("stateless"); s == "true" {
  119. return true
  120. }
  121. return false
  122. }
  123. // all except non-zero.
  124. func lookupFields(elem reflect.Value, skipUnexported bool, onlyZeros bool, parentIndex []int) (fields []reflect.StructField, stateless int) {
  125. // Note: embedded pointers are not supported.
  126. // elem = reflect.Indirect(elem)
  127. elemTyp := elem.Type()
  128. if elemTyp.Kind() == reflect.Pointer {
  129. return
  130. }
  131. for i, n := 0, elem.NumField(); i < n; i++ {
  132. field := elemTyp.Field(i)
  133. fieldValue := elem.Field(i)
  134. // embed any fields from other structs.
  135. if indirectType(field.Type).Kind() == reflect.Struct {
  136. if structFieldIgnored(field) {
  137. stateless++ // don't skip the loop yet, e.g. iris.Context.
  138. } else {
  139. structFields, statelessN := lookupFields(fieldValue, skipUnexported, onlyZeros, append(parentIndex, i))
  140. stateless += statelessN
  141. fields = append(fields, structFields...)
  142. continue
  143. }
  144. }
  145. if onlyZeros && !isZero(fieldValue) {
  146. continue
  147. }
  148. // skip unexported fields here.
  149. if isExported := field.PkgPath == ""; skipUnexported && !isExported {
  150. continue
  151. }
  152. index := []int{i}
  153. if len(parentIndex) > 0 {
  154. index = append(parentIndex, i)
  155. }
  156. tmp := make([]int, len(index))
  157. copy(tmp, index)
  158. field.Index = tmp
  159. fields = append(fields, field)
  160. }
  161. return
  162. }
  163. func lookupNonZeroFieldValues(elem reflect.Value) (nonZeroFields []reflect.StructField) {
  164. fields, _ := lookupFields(elem, true, false, nil)
  165. for _, f := range fields {
  166. if structFieldIgnored(f) {
  167. continue // re-check here for ignored struct fields so we don't include them on dependencies. Non-zeroes fields can be static, even if they are functions.
  168. }
  169. if fieldVal := elem.FieldByIndex(f.Index); goodVal(fieldVal) && !isZero(fieldVal) {
  170. /* && f.Type.Kind() == reflect.Ptr &&*/
  171. nonZeroFields = append(nonZeroFields, f)
  172. }
  173. }
  174. return
  175. }
  176. // isZero returns true if a value is nil.
  177. // Remember; fields to be checked should be exported otherwise it returns false.
  178. // Notes for users:
  179. // Boolean's zero value is false, even if not set-ed.
  180. // UintXX are not zero on 0 because they are pointers to.
  181. func isZero(v reflect.Value) bool {
  182. // switch v.Kind() {
  183. // case reflect.Struct:
  184. // zero := true
  185. // for i := 0; i < v.NumField(); i++ {
  186. // f := v.Field(i)
  187. // if f.Type().PkgPath() != "" {
  188. // continue // unexported.
  189. // }
  190. // zero = zero && isZero(f)
  191. // }
  192. // if typ := v.Type(); typ != nil && v.IsValid() {
  193. // f, ok := typ.MethodByName("IsZero")
  194. // // if not found
  195. // // if has input arguments (1 is for the value receiver, so > 1 for the actual input args)
  196. // // if output argument is not boolean
  197. // // then skip this IsZero user-defined function.
  198. // if !ok || f.Type.NumIn() > 1 || f.Type.NumOut() != 1 && f.Type.Out(0).Kind() != reflect.Bool {
  199. // return zero
  200. // }
  201. // method := v.Method(f.Index)
  202. // // no needed check but:
  203. // if method.IsValid() && !method.IsNil() {
  204. // // it shouldn't panic here.
  205. // zero = method.Call([]reflect.Value{})[0].Interface().(bool)
  206. // }
  207. // }
  208. // return zero
  209. // case reflect.Func, reflect.Map, reflect.Slice:
  210. // return v.IsNil()
  211. // case reflect.Array:
  212. // zero := true
  213. // for i := 0; i < v.Len(); i++ {
  214. // zero = zero && isZero(v.Index(i))
  215. // }
  216. // return zero
  217. // }
  218. // if not any special type then use the reflect's .Zero
  219. // usually for fields, but remember if it's boolean and it's false
  220. // then it's zero, even if set-ed.
  221. if !v.CanInterface() {
  222. // if can't interface, i.e return value from unexported field or method then return false
  223. return false
  224. }
  225. if v.Type() == ipTyp {
  226. return len(v.Interface().(net.IP)) == 0
  227. }
  228. // zero := reflect.Zero(v.Type())
  229. // return v.Interface() == zero.Interface()
  230. return v.IsZero()
  231. }
  232. // IsNil same as `reflect.IsNil` but a bit safer to use, returns false if not a correct type.
  233. func isNil(v reflect.Value) bool {
  234. k := v.Kind()
  235. switch k {
  236. case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
  237. return v.IsNil()
  238. default:
  239. return false
  240. }
  241. }