reflect.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. package hero
  2. import (
  3. "net"
  4. "reflect"
  5. "github.com/kataras/iris/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's.
  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. var (
  37. inputTyp = reflect.TypeOf((*Input)(nil))
  38. errTyp = reflect.TypeOf((*error)(nil)).Elem()
  39. ipTyp = reflect.TypeOf(net.IP{})
  40. )
  41. // isError returns true if "typ" is type of `error`.
  42. func isError(typ reflect.Type) bool {
  43. return typ.Implements(errTyp)
  44. }
  45. func toError(v reflect.Value) error {
  46. if v.IsNil() {
  47. return nil
  48. }
  49. return v.Interface().(error)
  50. }
  51. var contextType = reflect.TypeOf((*context.Context)(nil))
  52. // isContext returns true if the "typ" is a type of Context.
  53. func isContext(typ reflect.Type) bool {
  54. return typ == contextType
  55. }
  56. var errorHandlerTyp = reflect.TypeOf((*ErrorHandler)(nil)).Elem()
  57. func isErrorHandler(typ reflect.Type) bool {
  58. return typ.Implements(errorHandlerTyp)
  59. }
  60. var emptyValue reflect.Value
  61. func equalTypes(binding reflect.Type, input reflect.Type) bool {
  62. if binding == input {
  63. return true
  64. }
  65. // fmt.Printf("got: %s expected: %s\n", got.String(), expected.String())
  66. // if accepts an interface, check if the given "got" type does
  67. // implement this "expected" user handler's input argument.
  68. if input.Kind() == reflect.Interface {
  69. // fmt.Printf("expected interface = %s and got to set on the arg is: %s\n", binding.String(), input.String())
  70. // return input.Implements(binding)
  71. return binding.AssignableTo(input)
  72. }
  73. // dependency: func(...) interface{} { return "string" }
  74. // expected input: string.
  75. if binding.Kind() == reflect.Interface {
  76. return input.AssignableTo(binding)
  77. }
  78. return false
  79. }
  80. func structFieldIgnored(f reflect.StructField) bool {
  81. if !f.Anonymous {
  82. return true // if not anonymous(embedded), ignore it.
  83. }
  84. if s := f.Tag.Get("ignore"); s == "true" {
  85. return true
  86. }
  87. if s := f.Tag.Get("stateless"); s == "true" {
  88. return true
  89. }
  90. return false
  91. }
  92. // all except non-zero.
  93. func lookupFields(elem reflect.Value, skipUnexported bool, onlyZeros bool, parentIndex []int) (fields []reflect.StructField, stateless int) {
  94. elemTyp := elem.Type()
  95. for i, n := 0, elem.NumField(); i < n; i++ {
  96. field := elemTyp.Field(i)
  97. fieldValue := elem.Field(i)
  98. // embed any fields from other structs.
  99. if indirectType(field.Type).Kind() == reflect.Struct {
  100. if structFieldIgnored(field) {
  101. stateless++ // don't skip the loop yet, e.g. iris.Context.
  102. } else {
  103. structFields, statelessN := lookupFields(fieldValue, skipUnexported, onlyZeros, append(parentIndex, i))
  104. stateless += statelessN
  105. fields = append(fields, structFields...)
  106. continue
  107. }
  108. }
  109. if onlyZeros && !isZero(fieldValue) {
  110. continue
  111. }
  112. // skip unexported fields here.
  113. if isExported := field.PkgPath == ""; skipUnexported && !isExported {
  114. continue
  115. }
  116. index := []int{i}
  117. if len(parentIndex) > 0 {
  118. index = append(parentIndex, i)
  119. }
  120. tmp := make([]int, len(index))
  121. copy(tmp, index)
  122. field.Index = tmp
  123. fields = append(fields, field)
  124. }
  125. return
  126. }
  127. func lookupNonZeroFieldValues(elem reflect.Value) (nonZeroFields []reflect.StructField) {
  128. fields, _ := lookupFields(elem, true, false, nil)
  129. for _, f := range fields {
  130. if fieldVal := elem.FieldByIndex(f.Index); goodVal(fieldVal) && !isZero(fieldVal) {
  131. /* && f.Type.Kind() == reflect.Ptr &&*/
  132. nonZeroFields = append(nonZeroFields, f)
  133. }
  134. }
  135. return
  136. }
  137. // isZero returns true if a value is nil.
  138. // Remember; fields to be checked should be exported otherwise it returns false.
  139. // Notes for users:
  140. // Boolean's zero value is false, even if not set-ed.
  141. // UintXX are not zero on 0 because they are pointers to.
  142. func isZero(v reflect.Value) bool {
  143. // switch v.Kind() {
  144. // case reflect.Struct:
  145. // zero := true
  146. // for i := 0; i < v.NumField(); i++ {
  147. // f := v.Field(i)
  148. // if f.Type().PkgPath() != "" {
  149. // continue // unexported.
  150. // }
  151. // zero = zero && isZero(f)
  152. // }
  153. // if typ := v.Type(); typ != nil && v.IsValid() {
  154. // f, ok := typ.MethodByName("IsZero")
  155. // // if not found
  156. // // if has input arguments (1 is for the value receiver, so > 1 for the actual input args)
  157. // // if output argument is not boolean
  158. // // then skip this IsZero user-defined function.
  159. // if !ok || f.Type.NumIn() > 1 || f.Type.NumOut() != 1 && f.Type.Out(0).Kind() != reflect.Bool {
  160. // return zero
  161. // }
  162. // method := v.Method(f.Index)
  163. // // no needed check but:
  164. // if method.IsValid() && !method.IsNil() {
  165. // // it shouldn't panic here.
  166. // zero = method.Call([]reflect.Value{})[0].Interface().(bool)
  167. // }
  168. // }
  169. // return zero
  170. // case reflect.Func, reflect.Map, reflect.Slice:
  171. // return v.IsNil()
  172. // case reflect.Array:
  173. // zero := true
  174. // for i := 0; i < v.Len(); i++ {
  175. // zero = zero && isZero(v.Index(i))
  176. // }
  177. // return zero
  178. // }
  179. // if not any special type then use the reflect's .Zero
  180. // usually for fields, but remember if it's boolean and it's false
  181. // then it's zero, even if set-ed.
  182. if !v.CanInterface() {
  183. // if can't interface, i.e return value from unexported field or method then return false
  184. return false
  185. }
  186. if v.Type() == ipTyp {
  187. return len(v.Interface().(net.IP)) == 0
  188. }
  189. zero := reflect.Zero(v.Type())
  190. return v.Interface() == zero.Interface()
  191. }
  192. // IsNil same as `reflect.IsNil` but a bit safer to use, returns false if not a correct type.
  193. func isNil(v reflect.Value) bool {
  194. k := v.Kind()
  195. switch k {
  196. case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
  197. return v.IsNil()
  198. default:
  199. return false
  200. }
  201. }