-
Notifications
You must be signed in to change notification settings - Fork 10
/
encode.go
133 lines (127 loc) · 3.32 KB
/
encode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package easycsv
import (
"fmt"
"reflect"
"strconv"
)
var predefinedDecoders = map[string]func(t reflect.Type) interface{}{
"hex": func(t reflect.Type) interface{} {
return createIntConverter(t, 16)
},
"oct": func(t reflect.Type) interface{} {
return createIntConverter(t, 8)
},
"deci": func(t reflect.Type) interface{} {
return createIntConverter(t, 10)
},
}
func createIntConverter(t reflect.Type, base int) interface{} {
switch t.Kind() {
case reflect.Int:
return func(s string) (int, error) {
i, err := strconv.ParseInt(s, base, 0)
return int(i), err
}
case reflect.Int8:
return func(s string) (int8, error) {
i, err := strconv.ParseInt(s, base, 8)
return int8(i), err
}
case reflect.Int16:
return func(s string) (int16, error) {
i, err := strconv.ParseInt(s, base, 16)
return int16(i), err
}
case reflect.Int32:
return func(s string) (int32, error) {
i, err := strconv.ParseInt(s, base, 32)
return int32(i), err
}
case reflect.Int64:
return func(s string) (int64, error) {
i, err := strconv.ParseInt(s, base, 64)
return int64(i), err
}
case reflect.Uint:
return func(s string) (uint, error) {
i, err := strconv.ParseUint(s, base, 0)
return uint(i), err
}
case reflect.Uint8:
return func(s string) (uint8, error) {
i, err := strconv.ParseUint(s, base, 8)
return uint8(i), err
}
case reflect.Uint16:
return func(s string) (uint16, error) {
i, err := strconv.ParseUint(s, base, 16)
return uint16(i), err
}
case reflect.Uint32:
return func(s string) (uint32, error) {
i, err := strconv.ParseUint(s, base, 32)
return uint32(i), err
}
case reflect.Uint64:
return func(s string) (uint64, error) {
i, err := strconv.ParseUint(s, base, 32)
return uint64(i), err
}
default:
return nil
}
}
func validateTypeDecoder(t reflect.Type, conv interface{}) error {
convT := reflect.TypeOf(conv)
if convT.Kind() != reflect.Func {
return fmt.Errorf("The decoder for %v must be a function but %v", t, convT)
}
if convT.NumIn() != 1 || convT.NumOut() != 2 {
return fmt.Errorf("The decoder for %v must receive one arguments and returns two values", t)
}
if convT.In(0).Kind() != reflect.String {
return fmt.Errorf("The decoder for %v must receive a string as the first arg, but receives %v", t, convT.In(0))
}
if convT.Out(0) != t || convT.Out(1) != errorType {
return fmt.Errorf("The decoder for %v must return (%v, error), but returned (%v, %v)",
t, t, convT.Out(0), convT.Out(1))
}
return nil
}
func createConverterFromType(opt Option, t reflect.Type) (interface{}, error) {
if opt.TypeDecoders != nil {
if conv, ok := opt.TypeDecoders[t]; ok {
if err := validateTypeDecoder(t, conv); err != nil {
return nil, err
}
return conv, nil
}
}
return createDefaultConverter(t), nil
}
func createDefaultConverter(t reflect.Type) interface{} {
c := createIntConverter(t, 0)
if c != nil {
return c
}
switch t.Kind() {
case reflect.Float32:
return func(s string) (float32, error) {
f, err := strconv.ParseFloat(s, 32)
return float32(f), err
}
case reflect.Float64:
return func(s string) (float64, error) {
f, err := strconv.ParseFloat(s, 64)
return float64(f), err
}
case reflect.Bool:
return strconv.ParseBool
case reflect.String:
return func(s string) (string, error) {
return s, nil
}
default:
return nil
}
}