binder.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. package formbinder
  2. import (
  3. "fmt"
  4. "net/url"
  5. "reflect"
  6. "strconv"
  7. "time"
  8. )
  9. const tagName = "form"
  10. var timeFormat = []string{
  11. "2006-01-02",
  12. time.ANSIC,
  13. time.UnixDate,
  14. time.RubyDate,
  15. time.RFC822,
  16. time.RFC822Z,
  17. time.RFC850,
  18. time.RFC1123,
  19. time.RFC1123Z,
  20. time.RFC3339,
  21. time.RFC3339Nano,
  22. time.Kitchen,
  23. time.Stamp,
  24. time.StampMilli,
  25. time.StampMicro,
  26. time.StampNano,
  27. }
  28. // A pathMap holds the values of a map with its key and values correspondent
  29. type pathMap struct {
  30. ma reflect.Value
  31. key string
  32. value reflect.Value
  33. path string
  34. }
  35. // a pathMaps holds the values for each key
  36. type pathMaps []*pathMap
  37. // find find and get the value by the given key
  38. func (ma pathMaps) find(id reflect.Value, key string) *pathMap {
  39. for _, v := range ma {
  40. if v.ma == id && v.key == key {
  41. return v
  42. }
  43. }
  44. return nil
  45. }
  46. // DecodeCustomTypeFunc is a function that indicate how should to decode a custom type
  47. type DecodeCustomTypeFunc func([]string) (interface{}, error)
  48. // DecodeCustomTypeField is a function registered for a specific field of the struct passed to the Decoder
  49. type DecodeCustomTypeField struct {
  50. field reflect.Value
  51. fun DecodeCustomTypeFunc
  52. }
  53. // DecodeCustomType fields for custom types
  54. type DecodeCustomType struct {
  55. fun DecodeCustomTypeFunc
  56. fields []DecodeCustomTypeField
  57. }
  58. // Decoder the main to decode the values
  59. type Decoder struct {
  60. main reflect.Value
  61. formValues url.Values
  62. opts *DecoderOptions
  63. curr reflect.Value
  64. value string
  65. values []string
  66. path string
  67. field string
  68. bracket string
  69. isKey bool
  70. maps pathMaps
  71. customTypes map[reflect.Type]*DecodeCustomType
  72. }
  73. // DecoderOptions options for decoding the values
  74. type DecoderOptions struct {
  75. TagName string
  76. }
  77. // RegisterCustomType It is the method responsible for register functions for decoding custom types
  78. func (dec *Decoder) RegisterCustomType(fn DecodeCustomTypeFunc, types []interface{}, fields []interface{}) *Decoder {
  79. if dec.customTypes == nil {
  80. dec.customTypes = make(map[reflect.Type]*DecodeCustomType)
  81. }
  82. for i := range types {
  83. typ := reflect.TypeOf(types[i])
  84. if dec.customTypes[typ] == nil {
  85. dec.customTypes[typ] = new(DecodeCustomType)
  86. }
  87. if len(fields) > 0 {
  88. for j := range fields {
  89. va := reflect.ValueOf(fields[j])
  90. f := DecodeCustomTypeField{field: va, fun: fn}
  91. dec.customTypes[typ].fields = append(dec.customTypes[typ].fields, f)
  92. }
  93. } else {
  94. dec.customTypes[typ].fun = fn
  95. }
  96. }
  97. return dec
  98. }
  99. // NewDecoder creates a new instance of Decoder
  100. func NewDecoder(opts *DecoderOptions) *Decoder {
  101. dec := &Decoder{opts: opts}
  102. if dec.opts == nil {
  103. dec.opts = &DecoderOptions{}
  104. }
  105. if dec.opts.TagName == "" {
  106. dec.opts.TagName = tagName
  107. }
  108. return dec
  109. }
  110. // Decode decodes the url.Values into a element that must be a pointer to a type provided by argument
  111. func (dec *Decoder) Decode(vs url.Values, dst interface{}) error {
  112. main := reflect.ValueOf(dst)
  113. if main.Kind() != reflect.Ptr {
  114. return newError(fmt.Errorf("formam: the value passed for decode is not a pointer but a %v", main.Kind()))
  115. }
  116. dec.main = main.Elem()
  117. dec.formValues = vs
  118. return dec.prepare()
  119. }
  120. // Decode decodes the url.Values into a element that must be a pointer to a type provided by argument
  121. func Decode(vs url.Values, dst interface{}) error {
  122. main := reflect.ValueOf(dst)
  123. if main.Kind() != reflect.Ptr {
  124. return newError(fmt.Errorf("formam: the value passed for decode is not a pointer but a %v", main.Kind()))
  125. }
  126. dec := &Decoder{
  127. main: main.Elem(),
  128. formValues: vs,
  129. opts: &DecoderOptions{
  130. TagName: tagName,
  131. },
  132. }
  133. return dec.prepare()
  134. }
  135. func (dec *Decoder) prepare() error {
  136. // iterate over the form's values and decode it
  137. for k, v := range dec.formValues {
  138. dec.path = k
  139. dec.field = k
  140. dec.values = v
  141. dec.value = v[0]
  142. dec.curr = dec.main
  143. if dec.value != "" {
  144. if err := dec.begin(); err != nil {
  145. return err
  146. }
  147. }
  148. }
  149. // set values of maps
  150. for _, v := range dec.maps {
  151. key := v.ma.Type().Key()
  152. // check if the key implements the UnmarshalText interface
  153. var val reflect.Value
  154. if key.Kind() == reflect.Ptr {
  155. val = reflect.New(key.Elem())
  156. } else {
  157. val = reflect.New(key).Elem()
  158. }
  159. // decode key
  160. dec.path = v.path
  161. dec.field = v.path
  162. dec.values = []string{v.key}
  163. dec.curr = val
  164. dec.value = v.key
  165. dec.isKey = true
  166. if err := dec.decode(); err != nil {
  167. return err
  168. }
  169. // set key with its value
  170. v.ma.SetMapIndex(dec.curr, v.value)
  171. }
  172. dec.maps = make(pathMaps, 0)
  173. return nil
  174. }
  175. // begin analyzes the current path to walk through it
  176. func (dec *Decoder) begin() (err error) {
  177. inBracket := false
  178. valBracket := ""
  179. bracketClosed := false
  180. lastPos := 0
  181. tmp := dec.field
  182. // parse path
  183. for i, char := range tmp {
  184. if char == '[' && inBracket == false {
  185. // found an opening bracket
  186. bracketClosed = false
  187. inBracket = true
  188. dec.field = tmp[lastPos:i]
  189. lastPos = i + 1
  190. /*
  191. if err = dec.walk(); err != nil {
  192. return
  193. }
  194. */
  195. continue
  196. } else if inBracket {
  197. // it is inside of bracket, so get its value
  198. if char == ']' {
  199. /*
  200. nextChar := tmp[i+1:]
  201. if nextChar != "" {
  202. t := nextChar[:1]
  203. if t != "[" && t != "." {
  204. valBracket += string(char)
  205. continue
  206. }
  207. }
  208. */
  209. // found an closing bracket, so it will be recently close, so put as true the bracketClosed
  210. // and put as false inBracket and pass the value of bracket to dec.key
  211. inBracket = false
  212. bracketClosed = true
  213. dec.bracket = valBracket
  214. lastPos = i + 1
  215. if err = dec.walk(); err != nil {
  216. return
  217. }
  218. valBracket = ""
  219. } else {
  220. // still inside the bracket, so follow getting its value
  221. valBracket += string(char)
  222. }
  223. continue
  224. } else if !inBracket {
  225. // not found any bracket, so try found a field
  226. if char == '.' {
  227. // found a field, we need to know if the field is next of a closing bracket,
  228. // for example: [0].Field
  229. if bracketClosed {
  230. bracketClosed = false
  231. lastPos = i + 1
  232. continue
  233. }
  234. // found a field, but is not next of a closing bracket, for example: Field1.Field2
  235. dec.field = tmp[lastPos:i]
  236. //dec.field = tmp[:i]
  237. lastPos = i + 1
  238. if err = dec.walk(); err != nil {
  239. return
  240. }
  241. }
  242. continue
  243. }
  244. }
  245. // last field of path
  246. dec.field = tmp[lastPos:]
  247. return dec.end()
  248. }
  249. // walk traverses the current path until to the last field
  250. func (dec *Decoder) walk() error {
  251. // check if there is field, if is so, then it should be struct or map (access by .)
  252. if dec.field != "" {
  253. // check if is a struct or map
  254. switch dec.curr.Kind() {
  255. case reflect.Struct:
  256. if err := dec.findStructField(); err != nil {
  257. return err
  258. }
  259. case reflect.Map:
  260. dec.walkInMap(dec.field)
  261. }
  262. }
  263. // check if is a interface and it is not nil. This mean that the interface
  264. // has a struct, map or slice as value
  265. if dec.curr.Kind() == reflect.Interface && !dec.curr.IsNil() {
  266. dec.curr = dec.curr.Elem()
  267. }
  268. // check if it is a pointer
  269. if dec.curr.Kind() == reflect.Ptr {
  270. if dec.curr.IsNil() {
  271. dec.curr.Set(reflect.New(dec.curr.Type().Elem()))
  272. }
  273. dec.curr = dec.curr.Elem()
  274. }
  275. // check if there is access to slice/array or map (access by [])
  276. if dec.bracket != "" {
  277. switch dec.curr.Kind() {
  278. case reflect.Array:
  279. index, err := strconv.Atoi(dec.bracket)
  280. if err != nil {
  281. return newError(fmt.Errorf("formam: the index of array is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  282. }
  283. dec.curr = dec.curr.Index(index)
  284. case reflect.Slice:
  285. index, err := strconv.Atoi(dec.bracket)
  286. if err != nil {
  287. return newError(fmt.Errorf("formam: the index of slice is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  288. }
  289. if dec.curr.Len() <= index {
  290. dec.expandSlice(index + 1)
  291. }
  292. dec.curr = dec.curr.Index(index)
  293. case reflect.Map:
  294. dec.walkInMap(dec.bracket)
  295. default:
  296. return newError(fmt.Errorf("formam: the field \"%v\" in path \"%v\" has a index for array but it is a %v", dec.field, dec.path, dec.curr.Kind()))
  297. }
  298. }
  299. dec.field = ""
  300. dec.bracket = ""
  301. return nil
  302. }
  303. // walkMap puts in d.curr the map concrete for decode the current value
  304. func (dec *Decoder) walkInMap(key string) {
  305. n := dec.curr.Type()
  306. takeAndAppend := func() {
  307. m := reflect.New(n.Elem()).Elem()
  308. dec.maps = append(dec.maps, &pathMap{dec.curr, key, m, dec.path})
  309. dec.curr = m
  310. }
  311. if dec.curr.IsNil() {
  312. dec.curr.Set(reflect.MakeMap(n))
  313. takeAndAppend()
  314. } else if a := dec.maps.find(dec.curr, key); a == nil {
  315. takeAndAppend()
  316. } else {
  317. dec.curr = a.value
  318. }
  319. }
  320. // end finds the last field for decode its value correspondent
  321. func (dec *Decoder) end() error {
  322. switch dec.curr.Kind() {
  323. case reflect.Struct:
  324. if err := dec.findStructField(); err != nil {
  325. return err
  326. }
  327. case reflect.Map:
  328. // leave backward compatibility for access to maps by .
  329. dec.walkInMap(dec.field)
  330. }
  331. if dec.value == "" {
  332. return nil
  333. }
  334. return dec.decode()
  335. }
  336. // decode sets the value in the field
  337. func (dec *Decoder) decode() error {
  338. // has registered a custom type? If so, then decode by it
  339. if ok, err := dec.checkCustomType(); ok || err != nil {
  340. return err
  341. }
  342. // implements UnmarshalText interface? If so, then decode by it
  343. if ok, err := checkUnmarshalText(dec.curr, dec.value); ok || err != nil {
  344. return err
  345. }
  346. switch dec.curr.Kind() {
  347. case reflect.Array:
  348. if dec.bracket == "" {
  349. // not has index, so to decode all values in the array
  350. tmp := dec.curr
  351. for i, v := range dec.values {
  352. dec.curr = tmp.Index(i)
  353. dec.value = v
  354. if err := dec.decode(); err != nil {
  355. return err
  356. }
  357. }
  358. } else {
  359. // has index, so to decode value by index indicated
  360. index, err := strconv.Atoi(dec.bracket)
  361. if err != nil {
  362. return newError(fmt.Errorf("formam: the index of array is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  363. }
  364. dec.curr = dec.curr.Index(index)
  365. return dec.decode()
  366. }
  367. case reflect.Slice:
  368. if dec.bracket == "" {
  369. // not has index, so to decode all values in the slice/array
  370. dec.expandSlice(len(dec.values))
  371. tmp := dec.curr
  372. for i, v := range dec.values {
  373. dec.curr = tmp.Index(i)
  374. dec.value = v
  375. if err := dec.decode(); err != nil {
  376. return err
  377. }
  378. }
  379. } else {
  380. // has index, so to decode value by index indicated
  381. index, err := strconv.Atoi(dec.bracket)
  382. if err != nil {
  383. return newError(fmt.Errorf("formam: the index of slice is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  384. }
  385. if dec.curr.Len() <= index {
  386. dec.expandSlice(index + 1)
  387. }
  388. dec.curr = dec.curr.Index(index)
  389. return dec.decode()
  390. }
  391. case reflect.String:
  392. dec.curr.SetString(dec.value)
  393. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  394. if num, err := strconv.ParseInt(dec.value, 10, 64); err != nil {
  395. return newError(fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid signed integer number", dec.field, dec.path))
  396. } else {
  397. dec.curr.SetInt(num)
  398. }
  399. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  400. if num, err := strconv.ParseUint(dec.value, 10, 64); err != nil {
  401. return newError(fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid unsigned integer number", dec.field, dec.path))
  402. } else {
  403. dec.curr.SetUint(num)
  404. }
  405. case reflect.Float32, reflect.Float64:
  406. if num, err := strconv.ParseFloat(dec.value, dec.curr.Type().Bits()); err != nil {
  407. return newError(fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" should be a valid float number", dec.field, dec.path))
  408. } else {
  409. dec.curr.SetFloat(num)
  410. }
  411. case reflect.Bool:
  412. switch dec.value {
  413. case "true", "on", "1":
  414. dec.curr.SetBool(true)
  415. case "false", "off", "0":
  416. dec.curr.SetBool(false)
  417. default:
  418. return newError(fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid boolean", dec.field, dec.path))
  419. }
  420. case reflect.Interface:
  421. dec.curr.Set(reflect.ValueOf(dec.value))
  422. case reflect.Ptr:
  423. dec.curr.Set(reflect.New(dec.curr.Type().Elem()))
  424. dec.curr = dec.curr.Elem()
  425. return dec.decode()
  426. case reflect.Struct:
  427. switch dec.curr.Interface().(type) {
  428. case time.Time:
  429. var t time.Time
  430. var err error
  431. for _, layout := range timeFormat {
  432. t, err = time.Parse(layout, dec.value)
  433. if err == nil {
  434. break
  435. }
  436. }
  437. if err != nil {
  438. return newError(fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid datetime", dec.field, dec.path))
  439. }
  440. dec.curr.Set(reflect.ValueOf(t))
  441. case url.URL:
  442. u, err := url.Parse(dec.value)
  443. if err != nil {
  444. return newError(fmt.Errorf("formam: the value of field \"%v\" in path \"%v\" is not a valid url", dec.field, dec.path))
  445. }
  446. dec.curr.Set(reflect.ValueOf(*u))
  447. default:
  448. /*
  449. if dec.isKey {
  450. tmp := dec.curr
  451. dec.field = dec.value
  452. if err := dec.begin(); err != nil {
  453. return err
  454. }
  455. dec.curr = tmp
  456. return nil
  457. }
  458. */
  459. return newError(fmt.Errorf("formam: not supported type for field \"%v\" in path \"%v\"", dec.field, dec.path))
  460. }
  461. default:
  462. return newError(fmt.Errorf("formam: not supported type for field \"%v\" in path \"%v\"", dec.field, dec.path))
  463. }
  464. return nil
  465. }
  466. // findField finds a field by its name, if it is not found,
  467. // then retry the search examining the tag "formam" of every field of struct
  468. func (dec *Decoder) findStructField() error {
  469. var anon reflect.Value
  470. num := dec.curr.NumField()
  471. for i := 0; i < num; i++ {
  472. field := dec.curr.Type().Field(i)
  473. if field.Name == dec.field {
  474. // check if the field's name is equal
  475. dec.curr = dec.curr.Field(i)
  476. return nil
  477. } else if field.Anonymous {
  478. // if the field is a anonymous struct, then iterate over its fields
  479. tmp := dec.curr
  480. dec.curr = dec.curr.FieldByIndex(field.Index)
  481. if err := dec.findStructField(); err != nil {
  482. dec.curr = tmp
  483. continue
  484. }
  485. // field in anonymous struct is found,
  486. // but first it should found the field in the rest of struct
  487. // (a field with same name in the current struct should have preference over anonymous struct)
  488. anon = dec.curr
  489. dec.curr = tmp
  490. } else if dec.field == field.Tag.Get(dec.opts.TagName) {
  491. // is not found yet, then retry by its tag name "formam"
  492. dec.curr = dec.curr.Field(i)
  493. return nil
  494. }
  495. }
  496. if anon.IsValid() {
  497. dec.curr = anon
  498. return nil
  499. }
  500. return newError(fmt.Errorf("formam: not found the field \"%v\" in the path \"%v\"", dec.field, dec.path))
  501. }
  502. // expandSlice expands the length and capacity of the current slice
  503. func (dec *Decoder) expandSlice(length int) {
  504. n := reflect.MakeSlice(dec.curr.Type(), length, length)
  505. reflect.Copy(n, dec.curr)
  506. dec.curr.Set(n)
  507. }
  508. // checkCustomType checks if the value to decode has a custom type registered
  509. func (dec *Decoder) checkCustomType() (bool, error) {
  510. if dec.customTypes == nil {
  511. return false, nil
  512. }
  513. if v, ok := dec.customTypes[dec.curr.Type()]; ok {
  514. if len(v.fields) > 0 {
  515. for i := range v.fields {
  516. if v.fields[i].field.Elem() == dec.curr {
  517. va, err := v.fields[i].fun(dec.values)
  518. if err != nil {
  519. return true, err
  520. }
  521. dec.curr.Set(reflect.ValueOf(va))
  522. return true, nil
  523. }
  524. }
  525. if v.fun != nil {
  526. va, err := v.fun(dec.values)
  527. if err != nil {
  528. return true, err
  529. }
  530. dec.curr.Set(reflect.ValueOf(va))
  531. return true, nil
  532. }
  533. } else {
  534. va, err := v.fun(dec.values)
  535. if err != nil {
  536. return true, err
  537. }
  538. dec.curr.Set(reflect.ValueOf(va))
  539. return true, nil
  540. }
  541. }
  542. return false, nil
  543. }