decode.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. package ltsv
  2. import (
  3. "encoding"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. )
  9. // UnmarshalError is an error type for Unmarshal()
  10. type UnmarshalError map[string]error
  11. func (m UnmarshalError) Error() string {
  12. if len(m) == 0 {
  13. return "(no error)"
  14. }
  15. ee := make([]string, 0, len(m))
  16. for name, err := range m {
  17. ee = append(ee, fmt.Sprintf("field %q: %s", name, err))
  18. }
  19. return strings.Join(ee, "\n")
  20. }
  21. // OfField returns the error correspoinding to a given field
  22. func (m UnmarshalError) OfField(name string) error {
  23. return m[name]
  24. }
  25. // An UnmarshalTypeError describes a LTSV value that was
  26. // not appropriate for a value of a specific Go type.
  27. type UnmarshalTypeError struct {
  28. Value string
  29. Type reflect.Type
  30. }
  31. func (e *UnmarshalTypeError) Error() string {
  32. return "ltsv: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
  33. }
  34. type ltsvMap map[string]string
  35. func data2map(data []byte) (ltsvMap, error) {
  36. d := string(data)
  37. fields := strings.Split(d, "\t")
  38. l := ltsvMap{}
  39. for _, v := range fields {
  40. kv := strings.SplitN(strings.TrimSpace(v), ":", 2)
  41. if len(kv) != 2 {
  42. return nil, fmt.Errorf("not a ltsv: %s", d)
  43. }
  44. l[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
  45. }
  46. return l, nil
  47. }
  48. // Unmarshal parses the LTSV-encoded data and stores the result
  49. // in the value pointed to by v.
  50. func Unmarshal(data []byte, v interface{}) error {
  51. rv := reflect.ValueOf(v)
  52. if rv.Kind() != reflect.Ptr {
  53. return fmt.Errorf("not a pointer: %v", v)
  54. }
  55. rv = rv.Elem()
  56. if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map {
  57. return fmt.Errorf("not a pointer to a struct/map: %v", v)
  58. }
  59. l, err := data2map(data)
  60. if err != nil {
  61. return err
  62. }
  63. if rv.Kind() == reflect.Map {
  64. kt := rv.Type().Key()
  65. vt := rv.Type().Elem()
  66. if kt.Kind() != reflect.String || vt.Kind() != reflect.String {
  67. return fmt.Errorf("not a map[string]string")
  68. }
  69. for k, v := range l {
  70. kv := reflect.ValueOf(k).Convert(kt)
  71. vv := reflect.ValueOf(v).Convert(vt)
  72. rv.SetMapIndex(kv, vv)
  73. }
  74. return nil
  75. }
  76. t := rv.Type()
  77. errs := UnmarshalError{}
  78. for i := 0; i < t.NumField(); i++ {
  79. ft := t.Field(i)
  80. fv := rv.Field(i)
  81. tag := ft.Tag.Get("ltsv")
  82. tags := strings.Split(tag, ",")
  83. key := tags[0]
  84. if key == "-" {
  85. continue
  86. }
  87. if key == "" {
  88. key = strings.ToLower(ft.Name)
  89. }
  90. s, ok := l[key]
  91. if !ok {
  92. continue
  93. }
  94. potentiallyNull := s == "-" || s == ""
  95. if fv.Kind() == reflect.Ptr {
  96. if fv.IsNil() {
  97. if potentiallyNull {
  98. switch fv.Type().Elem().Kind() {
  99. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
  100. continue
  101. }
  102. }
  103. fv.Set(reflect.New(fv.Type().Elem()))
  104. }
  105. fv = fv.Elem()
  106. }
  107. if !fv.CanSet() {
  108. continue
  109. }
  110. switch fv.Kind() {
  111. case reflect.String:
  112. fv.SetString(s)
  113. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  114. if potentiallyNull {
  115. continue
  116. }
  117. i, err := strconv.ParseInt(s, 10, 64)
  118. if err != nil || fv.OverflowInt(i) {
  119. errs[ft.Name] = &UnmarshalTypeError{"number " + s, fv.Type()}
  120. continue
  121. }
  122. fv.SetInt(i)
  123. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  124. if potentiallyNull {
  125. continue
  126. }
  127. i, err := strconv.ParseUint(s, 10, 64)
  128. if err != nil || fv.OverflowUint(i) {
  129. errs[ft.Name] = &UnmarshalTypeError{"number " + s, fv.Type()}
  130. continue
  131. }
  132. fv.SetUint(i)
  133. case reflect.Float32, reflect.Float64:
  134. if potentiallyNull {
  135. continue
  136. }
  137. n, err := strconv.ParseFloat(s, fv.Type().Bits())
  138. if err != nil || fv.OverflowFloat(n) {
  139. errs[ft.Name] = &UnmarshalTypeError{"number " + s, fv.Type()}
  140. continue
  141. }
  142. fv.SetFloat(n)
  143. default:
  144. u := indirect(fv)
  145. if u == nil {
  146. errs[ft.Name] = &UnmarshalTypeError{s, fv.Type()}
  147. } else {
  148. err := u.UnmarshalText([]byte(s))
  149. if err != nil {
  150. errs[ft.Name] = err
  151. }
  152. }
  153. }
  154. }
  155. if len(errs) < 1 {
  156. return nil
  157. }
  158. return errs
  159. }
  160. func indirect(v reflect.Value) encoding.TextUnmarshaler {
  161. if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
  162. v = v.Addr()
  163. }
  164. for {
  165. if v.Kind() == reflect.Interface && !v.IsNil() {
  166. e := v.Elem()
  167. if e.Kind() == reflect.Ptr && !e.IsNil() && e.Elem().Kind() == reflect.Ptr {
  168. v = e
  169. continue
  170. }
  171. }
  172. if v.Kind() != reflect.Ptr {
  173. break
  174. }
  175. if v.Elem().Kind() != reflect.Ptr && v.CanSet() {
  176. break
  177. }
  178. if v.IsNil() {
  179. v.Set(reflect.New(v.Type().Elem()))
  180. }
  181. if v.Type().NumMethod() > 0 {
  182. if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
  183. return u
  184. }
  185. }
  186. }
  187. return nil
  188. }