option_private.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package flags
  2. import (
  3. "reflect"
  4. )
  5. // Set the value of an option to the specified value. An error will be returned
  6. // if the specified value could not be converted to the corresponding option
  7. // value type.
  8. func (option *Option) set(value *string) error {
  9. if option.isFunc() {
  10. return option.call(value)
  11. } else if value != nil {
  12. return convert(*value, option.value, option.tag)
  13. } else {
  14. return convert("", option.value, option.tag)
  15. }
  16. return nil
  17. }
  18. func (option *Option) canCli() bool {
  19. return option.ShortName != 0 || len(option.LongName) != 0
  20. }
  21. func (option *Option) canArgument() bool {
  22. if u := option.isUnmarshaler(); u != nil {
  23. return true
  24. }
  25. return !option.isBool()
  26. }
  27. func (option *Option) clear() {
  28. tp := option.value.Type()
  29. switch tp.Kind() {
  30. case reflect.Func:
  31. // Skip
  32. case reflect.Map:
  33. // Empty the map
  34. option.value.Set(reflect.MakeMap(tp))
  35. default:
  36. zeroval := reflect.Zero(tp)
  37. option.value.Set(zeroval)
  38. }
  39. }
  40. func (option *Option) isUnmarshaler() Unmarshaler {
  41. v := option.value
  42. for {
  43. if !v.CanInterface() {
  44. return nil
  45. }
  46. i := v.Interface()
  47. if u, ok := i.(Unmarshaler); ok {
  48. return u
  49. }
  50. if !v.CanAddr() {
  51. return nil
  52. }
  53. v = v.Addr()
  54. }
  55. return nil
  56. }
  57. func (option *Option) isBool() bool {
  58. tp := option.value.Type()
  59. for {
  60. switch tp.Kind() {
  61. case reflect.Bool:
  62. return true
  63. case reflect.Slice:
  64. return (tp.Elem().Kind() == reflect.Bool)
  65. case reflect.Func:
  66. return tp.NumIn() == 0
  67. case reflect.Ptr:
  68. tp = tp.Elem()
  69. default:
  70. return false
  71. }
  72. }
  73. return false
  74. }
  75. func (option *Option) isFunc() bool {
  76. return option.value.Type().Kind() == reflect.Func
  77. }
  78. func (option *Option) call(value *string) error {
  79. var retval []reflect.Value
  80. if value == nil {
  81. retval = option.value.Call(nil)
  82. } else {
  83. tp := option.value.Type().In(0)
  84. val := reflect.New(tp)
  85. val = reflect.Indirect(val)
  86. if err := convert(*value, val, option.tag); err != nil {
  87. return err
  88. }
  89. retval = option.value.Call([]reflect.Value{val})
  90. }
  91. if len(retval) == 1 && retval[0].Type() == reflect.TypeOf((*error)(nil)).Elem() {
  92. if retval[0].Interface() == nil {
  93. return nil
  94. }
  95. return retval[0].Interface().(error)
  96. }
  97. return nil
  98. }