Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

249 rader
6.9 KiB

  1. package altsrc
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "time"
  7. "gopkg.in/urfave/cli.v1"
  8. )
  9. // MapInputSource implements InputSourceContext to return
  10. // data from the map that is loaded.
  11. type MapInputSource struct {
  12. valueMap map[interface{}]interface{}
  13. }
  14. // nestedVal checks if the name has '.' delimiters.
  15. // If so, it tries to traverse the tree by the '.' delimited sections to find
  16. // a nested value for the key.
  17. func nestedVal(name string, tree map[interface{}]interface{}) (interface{}, bool) {
  18. if sections := strings.Split(name, "."); len(sections) > 1 {
  19. node := tree
  20. for _, section := range sections[:len(sections)-1] {
  21. if child, ok := node[section]; !ok {
  22. return nil, false
  23. } else {
  24. if ctype, ok := child.(map[interface{}]interface{}); !ok {
  25. return nil, false
  26. } else {
  27. node = ctype
  28. }
  29. }
  30. }
  31. if val, ok := node[sections[len(sections)-1]]; ok {
  32. return val, true
  33. }
  34. }
  35. return nil, false
  36. }
  37. // Int returns an int from the map if it exists otherwise returns 0
  38. func (fsm *MapInputSource) Int(name string) (int, error) {
  39. otherGenericValue, exists := fsm.valueMap[name]
  40. if exists {
  41. otherValue, isType := otherGenericValue.(int)
  42. if !isType {
  43. return 0, incorrectTypeForFlagError(name, "int", otherGenericValue)
  44. }
  45. return otherValue, nil
  46. }
  47. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  48. if exists {
  49. otherValue, isType := nestedGenericValue.(int)
  50. if !isType {
  51. return 0, incorrectTypeForFlagError(name, "int", nestedGenericValue)
  52. }
  53. return otherValue, nil
  54. }
  55. return 0, nil
  56. }
  57. // Duration returns a duration from the map if it exists otherwise returns 0
  58. func (fsm *MapInputSource) Duration(name string) (time.Duration, error) {
  59. otherGenericValue, exists := fsm.valueMap[name]
  60. if exists {
  61. otherValue, isType := otherGenericValue.(time.Duration)
  62. if !isType {
  63. return 0, incorrectTypeForFlagError(name, "duration", otherGenericValue)
  64. }
  65. return otherValue, nil
  66. }
  67. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  68. if exists {
  69. otherValue, isType := nestedGenericValue.(time.Duration)
  70. if !isType {
  71. return 0, incorrectTypeForFlagError(name, "duration", nestedGenericValue)
  72. }
  73. return otherValue, nil
  74. }
  75. return 0, nil
  76. }
  77. // Float64 returns an float64 from the map if it exists otherwise returns 0
  78. func (fsm *MapInputSource) Float64(name string) (float64, error) {
  79. otherGenericValue, exists := fsm.valueMap[name]
  80. if exists {
  81. otherValue, isType := otherGenericValue.(float64)
  82. if !isType {
  83. return 0, incorrectTypeForFlagError(name, "float64", otherGenericValue)
  84. }
  85. return otherValue, nil
  86. }
  87. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  88. if exists {
  89. otherValue, isType := nestedGenericValue.(float64)
  90. if !isType {
  91. return 0, incorrectTypeForFlagError(name, "float64", nestedGenericValue)
  92. }
  93. return otherValue, nil
  94. }
  95. return 0, nil
  96. }
  97. // String returns a string from the map if it exists otherwise returns an empty string
  98. func (fsm *MapInputSource) String(name string) (string, error) {
  99. otherGenericValue, exists := fsm.valueMap[name]
  100. if exists {
  101. otherValue, isType := otherGenericValue.(string)
  102. if !isType {
  103. return "", incorrectTypeForFlagError(name, "string", otherGenericValue)
  104. }
  105. return otherValue, nil
  106. }
  107. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  108. if exists {
  109. otherValue, isType := nestedGenericValue.(string)
  110. if !isType {
  111. return "", incorrectTypeForFlagError(name, "string", nestedGenericValue)
  112. }
  113. return otherValue, nil
  114. }
  115. return "", nil
  116. }
  117. // StringSlice returns an []string from the map if it exists otherwise returns nil
  118. func (fsm *MapInputSource) StringSlice(name string) ([]string, error) {
  119. otherGenericValue, exists := fsm.valueMap[name]
  120. if exists {
  121. otherValue, isType := otherGenericValue.([]string)
  122. if !isType {
  123. return nil, incorrectTypeForFlagError(name, "[]string", otherGenericValue)
  124. }
  125. return otherValue, nil
  126. }
  127. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  128. if exists {
  129. otherValue, isType := nestedGenericValue.([]string)
  130. if !isType {
  131. return nil, incorrectTypeForFlagError(name, "[]string", nestedGenericValue)
  132. }
  133. return otherValue, nil
  134. }
  135. return nil, nil
  136. }
  137. // IntSlice returns an []int from the map if it exists otherwise returns nil
  138. func (fsm *MapInputSource) IntSlice(name string) ([]int, error) {
  139. otherGenericValue, exists := fsm.valueMap[name]
  140. if exists {
  141. otherValue, isType := otherGenericValue.([]int)
  142. if !isType {
  143. return nil, incorrectTypeForFlagError(name, "[]int", otherGenericValue)
  144. }
  145. return otherValue, nil
  146. }
  147. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  148. if exists {
  149. otherValue, isType := nestedGenericValue.([]int)
  150. if !isType {
  151. return nil, incorrectTypeForFlagError(name, "[]int", nestedGenericValue)
  152. }
  153. return otherValue, nil
  154. }
  155. return nil, nil
  156. }
  157. // Generic returns an cli.Generic from the map if it exists otherwise returns nil
  158. func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) {
  159. otherGenericValue, exists := fsm.valueMap[name]
  160. if exists {
  161. otherValue, isType := otherGenericValue.(cli.Generic)
  162. if !isType {
  163. return nil, incorrectTypeForFlagError(name, "cli.Generic", otherGenericValue)
  164. }
  165. return otherValue, nil
  166. }
  167. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  168. if exists {
  169. otherValue, isType := nestedGenericValue.(cli.Generic)
  170. if !isType {
  171. return nil, incorrectTypeForFlagError(name, "cli.Generic", nestedGenericValue)
  172. }
  173. return otherValue, nil
  174. }
  175. return nil, nil
  176. }
  177. // Bool returns an bool from the map otherwise returns false
  178. func (fsm *MapInputSource) Bool(name string) (bool, error) {
  179. otherGenericValue, exists := fsm.valueMap[name]
  180. if exists {
  181. otherValue, isType := otherGenericValue.(bool)
  182. if !isType {
  183. return false, incorrectTypeForFlagError(name, "bool", otherGenericValue)
  184. }
  185. return otherValue, nil
  186. }
  187. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  188. if exists {
  189. otherValue, isType := nestedGenericValue.(bool)
  190. if !isType {
  191. return false, incorrectTypeForFlagError(name, "bool", nestedGenericValue)
  192. }
  193. return otherValue, nil
  194. }
  195. return false, nil
  196. }
  197. // BoolT returns an bool from the map otherwise returns true
  198. func (fsm *MapInputSource) BoolT(name string) (bool, error) {
  199. otherGenericValue, exists := fsm.valueMap[name]
  200. if exists {
  201. otherValue, isType := otherGenericValue.(bool)
  202. if !isType {
  203. return true, incorrectTypeForFlagError(name, "bool", otherGenericValue)
  204. }
  205. return otherValue, nil
  206. }
  207. nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
  208. if exists {
  209. otherValue, isType := nestedGenericValue.(bool)
  210. if !isType {
  211. return true, incorrectTypeForFlagError(name, "bool", nestedGenericValue)
  212. }
  213. return otherValue, nil
  214. }
  215. return true, nil
  216. }
  217. func incorrectTypeForFlagError(name, expectedTypeName string, value interface{}) error {
  218. valueType := reflect.TypeOf(value)
  219. valueTypeName := ""
  220. if valueType != nil {
  221. valueTypeName = valueType.Name()
  222. }
  223. return fmt.Errorf("Mismatched type for flag '%s'. Expected '%s' but actual is '%s'", name, expectedTypeName, valueTypeName)
  224. }