-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcomposite.go
58 lines (56 loc) · 1.23 KB
/
composite.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
package typ
import (
"reflect"
)
// Get retrieve value from composite type, argument values used as index keys
func (t *Type) Get(argIndexes ...interface{}) (typ *Type) {
if !t.rv.IsValid() {
return NewType(nil, ErrInvalidArgument)
}
var (
p = t.rv
cnt = len(argIndexes)
i int
)
defer func() {
if r := recover(); r != nil {
typ = NewType(nil, ErrInvalidArgument)
}
}()
for ; i < cnt; i++ {
switch p.Kind() {
case reflect.Slice, reflect.Array:
index, ok := argIndexes[i].(int)
if !ok {
return NewType(nil, ErrInvalidArgument)
}
if index < 0 || index > p.Len()-1 {
return NewType(nil, ErrOutOfRange)
}
if p = p.Index(index); p.Interface() == nil {
return NewType(nil, ErrOutOfBounds)
}
if p.Kind() == reflect.Interface {
p = p.Elem()
}
case reflect.Map:
if p = p.MapIndex(reflect.ValueOf(argIndexes[i])); !p.IsValid() {
return NewType(nil, ErrOutOfBounds)
}
if p.Kind() == reflect.Interface {
p = p.Elem()
}
default:
return NewType(nil, ErrUnexpectedValue)
}
if i == cnt-1 {
typed := &Type{
rv: reflect.ValueOf(p.Interface()),
opts: t.opts,
}
typed.kind = typed.rv.Kind()
return typed
}
}
return NewType(nil, ErrInvalidArgument)
}