-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.go
More file actions
200 lines (182 loc) · 5.8 KB
/
parser.go
File metadata and controls
200 lines (182 loc) · 5.8 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package defaults
import (
"errors"
"fmt"
"reflect"
"strconv"
"time"
"github.com/segmentio/encoding/json"
)
// ErrUnsupportedType is an error returned when attempting to parse an unsupported type.
var ErrUnsupportedType = errors.New("unsupported type")
// ParserFunc defines a function type for parsing a string into a reflect.Value
// based on the specified reflect.Type, returning the parsed value and any error encountered.
type ParserFunc func(str string, t reflect.Type) (reflect.Value, error)
var parser = map[string]ParserFunc{
reflect.Int.String(): ParseInt,
reflect.Int8.String(): ParseInt,
reflect.Int16.String(): ParseInt,
reflect.Int32.String(): ParseInt,
reflect.Int64.String(): ParseInt,
reflect.Uint.String(): ParseUint,
reflect.Uint8.String(): ParseUint,
reflect.Uint16.String(): ParseUint,
reflect.Uint32.String(): ParseUint,
reflect.Uint64.String(): ParseUint,
reflect.Float32.String(): ParseFloat,
reflect.Float64.String(): ParseFloat,
reflect.Complex64.String(): ParseComplex,
reflect.Complex128.String(): ParseComplex,
reflect.Bool.String(): ParseBool,
reflect.String.String(): ParseString,
reflect.TypeOf(time.Duration(0)).String(): ParseDuration,
reflect.Map.String(): ParseMap,
reflect.Slice.String(): ParseSlice,
reflect.Array.String(): ParseArray,
}
// ParseInt parses a string to an integer type (int, int8, int16, int32, int64).
func ParseInt(str string, t reflect.Type) (reflect.Value, error) {
var bitSize int
switch t.Kind() {
case reflect.Int8:
bitSize = 8
case reflect.Int16:
bitSize = 16
case reflect.Int32:
bitSize = 32
case reflect.Int64:
bitSize = 64
default:
bitSize = 0
}
val, err := strconv.ParseInt(str, 0, bitSize)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(val).Convert(t), nil
}
// ParseUint parses a string to an unsigned integer type (uint, uint8, uint16, uint32, uint64).
func ParseUint(str string, t reflect.Type) (reflect.Value, error) {
var bitSize int
switch t.Kind() {
case reflect.Uint8:
bitSize = 8
case reflect.Uint16:
bitSize = 16
case reflect.Uint32:
bitSize = 32
case reflect.Uint64:
bitSize = 64
default:
bitSize = 0
}
val, err := strconv.ParseUint(str, 0, bitSize)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(val).Convert(t), nil
}
// ParseFloat parses a string to a float type (float32, float64).
func ParseFloat(str string, t reflect.Type) (reflect.Value, error) {
var bitSize int
switch t.Kind() {
case reflect.Float32:
bitSize = 32
case reflect.Float64:
bitSize = 64
default:
return reflect.Value{}, ErrUnsupportedType
}
val, err := strconv.ParseFloat(str, bitSize)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(val).Convert(t), nil
}
// ParseComplex parses a string to a complex type (complex64, complex128).
func ParseComplex(str string, t reflect.Type) (reflect.Value, error) {
var bitSize int
switch t.Kind() {
case reflect.Complex64:
bitSize = 64
case reflect.Complex128:
bitSize = 128
default:
return reflect.Value{}, ErrUnsupportedType
}
val, err := strconv.ParseComplex(str, bitSize)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(val).Convert(t), nil
}
// ParseBool parses a string to a boolean.
func ParseBool(str string, t reflect.Type) (reflect.Value, error) {
val, err := strconv.ParseBool(str)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(val).Convert(t), nil
}
// ParseString parses a string to a string.
func ParseString(str string, t reflect.Type) (reflect.Value, error) {
return reflect.ValueOf(str).Convert(t), nil
}
// ParseDuration parses a string to a time.Duration.
func ParseDuration(str string, t reflect.Type) (reflect.Value, error) {
val, err := time.ParseDuration(str)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(val).Convert(t), nil
}
// ParseMap parses a JSON-like string to a map.
func ParseMap(str string, t reflect.Type) (reflect.Value, error) {
if t.Kind() != reflect.Map {
return reflect.Value{}, fmt.Errorf("t is not a map")
}
val := reflect.New(t)
if err := json.Unmarshal([]byte(str), val.Interface()); err != nil {
return reflect.Value{}, fmt.Errorf("invalid map format: %w", err)
}
return val.Elem(), nil
}
// ParseSlice parses a JSON-like string to a slice.
func ParseSlice(str string, t reflect.Type) (reflect.Value, error) {
if t.Kind() != reflect.Slice {
return reflect.Value{}, fmt.Errorf("t is not a slice")
}
val := reflect.New(t)
if err := json.Unmarshal([]byte(str), val.Interface()); err != nil {
return reflect.Value{}, fmt.Errorf("invalid slice format: %w", err)
}
return val.Elem(), nil
}
// ParseArray parses a JSON-like string to an array.
func ParseArray(str string, t reflect.Type) (reflect.Value, error) {
if t.Kind() != reflect.Array {
return reflect.Value{}, fmt.Errorf("t is not an array")
}
// Parse into a slice first
elemType := t.Elem()
tempSlicePtr := reflect.New(reflect.SliceOf(elemType))
if err := json.Unmarshal([]byte(str), tempSlicePtr.Interface()); err != nil {
return reflect.Value{}, fmt.Errorf("invalid array format: %w", err)
}
// Check if enough space
tempSlice := tempSlicePtr.Elem()
expectedLen := t.Len()
if tempSlice.Len() > expectedLen {
return reflect.Value{}, fmt.Errorf(
"array length %d exceeds capacity %d",
tempSlice.Len(),
expectedLen,
)
}
// Append values
arrayVal := reflect.New(t).Elem()
for i := range tempSlice.Len() {
arrayVal.Index(i).Set(tempSlice.Index(i))
}
return arrayVal, nil
}