-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcoerce.go
More file actions
46 lines (42 loc) · 1.12 KB
/
Copy pathcoerce.go
File metadata and controls
46 lines (42 loc) · 1.12 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
package parse
import (
"reflect"
"github.com/ohait/forego/ctx"
)
// coerce the given value to the given type
// optionally creating new slices of the right type
func coerce(in reflect.Value, t reflect.Type) (reflect.Value, error) {
if !in.IsValid() {
return reflect.New(t).Elem(), nil // return zero value
}
if in.IsZero() && t.Kind() != reflect.Interface {
return reflect.New(t).Elem(), nil // return zero value
}
if in.Kind() == reflect.Interface {
in = in.Elem()
}
if in.Type() == t {
return in, nil
}
//log.Printf("coerce in: %v, t: %+v", in.Type(), t)
if t.Kind() == reflect.Slice && in.Kind() == reflect.Slice {
return coerceSlice(in, t)
}
if !in.CanConvert(t) {
return in, ctx.NewErrorf(nil, "can't convert %v to %v", in.Type(), t)
}
in = in.Convert(t)
return in, nil
}
func coerceSlice(in reflect.Value, t reflect.Type) (reflect.Value, error) {
//log.Printf("coerceSlice(%v => %v)", in.Type(), t)
out := reflect.MakeSlice(t, in.Len(), in.Len())
for i := 0; i < in.Len(); i++ {
v, err := coerce(in.Index(i), t.Elem())
if err != nil {
return in, err
}
out.Index(i).Set(v)
}
return out, nil
}