forked from Ompluscator/dynamic-struct
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwriter_map.go
135 lines (128 loc) · 3.17 KB
/
writer_map.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
134
135
package dynamicstruct
import (
"errors"
"reflect"
"strings"
)
type mapImpl struct {
mapWriters map[any]Writer
value reflect.Value
field reflect.StructField
}
func (s *mapImpl) Set(value any) (err error) {
defer func() {
er := recover()
if er != nil {
err = errors.New(er.(string))
}
}()
//todo 判断map类型是否一致
s.value.Set(reflect.ValueOf(value))
return
}
func (s *mapImpl) Get() (any, bool) {
return s.value.Interface(), true
}
// can set struct.substruct field value
func (s *mapImpl) linkSet(names []string, value any) error {
if len(names) == 0 {
return s.Set(value)
}
key := names[0]
if len(names) == 1 {
if value == nil { //delete
reflect.Indirect(s.value).SetMapIndex(reflect.ValueOf(key), reflect.Value{})
} else {
switch res := value.(type) {
case reflect.Value:
reflect.Indirect(s.value).SetMapIndex(reflect.ValueOf(key), res)
default:
reflect.Indirect(s.value).SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(value))
}
}
return nil
}
var writer Writer
var err error
var found bool
writer, found = s.mapWriters[key]
var x reflect.Value
if !found {
sub := reflect.Indirect(s.value).MapIndex(reflect.Indirect(reflect.ValueOf(key)))
if sub.IsValid() {
x = reflect.New(sub.Type())
x.Elem().Set(sub)
} else {
x = reflect.New(s.value.Type().Elem())
}
writer, err = subWriter(x)
if err != nil {
return err // todo 优化报错
}
s.mapWriters[key] = writer
} // todo map修改失效?
ret := writer.linkSet(names[1:], value)
if ret == nil {
reflect.Indirect(s.value).SetMapIndex(reflect.ValueOf(key), reflect.Indirect(x))
}
return ret
}
// can set struct.substruct field value
func (s *mapImpl) LinkSet(linkName string, value any) error {
return s.linkSet(strings.Split(linkName, SqliteSeq), value)
}
func (s *mapImpl) LinkGet(linkName string) (any, bool) {
return s.linkGet(strings.Split(linkName, SqliteSeq))
}
// can set struct.substruct field value
func (s *mapImpl) linkGet(names []string) (any, bool) {
if len(names) == 0 {
return s.Get()
}
key := names[0]
if len(names) == 1 {
ret := reflect.Indirect(s.value).MapIndex(reflect.Indirect(reflect.ValueOf(key)))
if ret.IsValid() {
return ret.Interface(), true
}
return nil, false
}
var writer Writer
var err error
var found bool
writer, found = s.mapWriters[key]
if !found {
sub := reflect.Indirect(s.value).MapIndex(reflect.Indirect(reflect.ValueOf(key)))
var x reflect.Value
if sub.IsValid() {
x = reflect.New(sub.Type())
x.Elem().Set(sub)
} else {
return nil, false
}
writer, err = subWriter(x)
if err != nil {
return nil, false // todo 优化报错
}
s.mapWriters[key] = writer
}
return writer.linkGet(names[1:])
}
func (s *mapImpl) Type() reflect.Type {
return s.field.Type
}
func (s *mapImpl) linkTyp(names []string) (reflect.Type, bool) {
if len(names) == 0 {
return s.Type(), true
}
var x reflect.Value
x = reflect.New(s.value.Type().Elem())
writer, err := subWriter(x)
if err != nil {
return nil, false // todo 优化报错
}
return writer.linkTyp(names[1:])
}
func (s *mapImpl) LinkTyp(linkName string) (reflect.Type, bool) {
return s.linkTyp(strings.Split(linkName, SqliteSeq))
}