You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
1.8KB

  1. package cache
  2. import (
  3. "fmt"
  4. "reflect"
  5. "time"
  6. )
  7. // TypeAssert assert source to target.
  8. func TypeAssert(source, target interface{}) (err error) {
  9. if source == nil {
  10. return nil
  11. }
  12. if directTypeAssert(source, target) {
  13. return nil
  14. }
  15. v := reflect.ValueOf(target)
  16. if !v.IsValid() {
  17. return fmt.Errorf("%w", ErrTargetNil)
  18. }
  19. if v.Kind() != reflect.Ptr {
  20. return NewErrorTarget(target)
  21. }
  22. v = v.Elem()
  23. if !v.IsValid() {
  24. return NewErrorTarget(target)
  25. }
  26. s := reflect.ValueOf(source)
  27. if !s.IsValid() {
  28. return fmt.Errorf("%w", ErrSourceNotValid)
  29. }
  30. s = deReference(s)
  31. v.Set(s)
  32. return nil
  33. }
  34. // nolint: gocyclo
  35. func directTypeAssert(source, target interface{}) bool {
  36. var ok bool
  37. switch v := target.(type) {
  38. case *string:
  39. *v, ok = source.(string)
  40. case *[]byte:
  41. *v, ok = source.([]byte)
  42. case *int:
  43. *v, ok = source.(int)
  44. case *int8:
  45. *v, ok = source.(int8)
  46. case *int16:
  47. *v, ok = source.(int16)
  48. case *int32:
  49. *v, ok = source.(int32)
  50. case *int64:
  51. *v, ok = source.(int64)
  52. case *uint:
  53. *v, ok = source.(uint)
  54. case *uint8:
  55. *v, ok = source.(uint8)
  56. case *uint16:
  57. *v, ok = source.(uint16)
  58. case *uint32:
  59. *v, ok = source.(uint32)
  60. case *uint64:
  61. *v, ok = source.(uint64)
  62. case *bool:
  63. *v, ok = source.(bool)
  64. case *float32:
  65. *v, ok = source.(float32)
  66. case *float64:
  67. *v, ok = source.(float64)
  68. case *time.Duration:
  69. *v, ok = source.(time.Duration)
  70. case *time.Time:
  71. *v, ok = source.(time.Time)
  72. case *[]string:
  73. *v, ok = source.([]string)
  74. case *map[string]string:
  75. *v, ok = source.(map[string]string)
  76. case *map[string]interface{}:
  77. *v, ok = source.(map[string]interface{})
  78. }
  79. return ok
  80. }
  81. func deReference(v reflect.Value) reflect.Value {
  82. if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && !v.IsNil() {
  83. return v.Elem()
  84. }
  85. return v
  86. }