forked from Ompluscator/dynamic-struct
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwriter_slice.go
150 lines (139 loc) · 3.44 KB
/
writer_slice.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package dynamicstruct
import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
)
type sliceImpl struct {
value reflect.Value
field reflect.StructField
sliceToMap string //以map形式存储切片
mapWriters map[any]Writer
}
func (s *sliceImpl) Set(value any) (err error) {
defer func() {
er := recover()
if er != nil {
err = errors.New(er.(string))
}
}()
s.value.Set(reflect.ValueOf(value))
s.mapWriters = make(map[any]Writer)
return
}
func (s *sliceImpl) Get() (any, bool) {
return s.value.Interface(), true
}
// can set struct.substruct field value
func (s *sliceImpl) linkSet(names []string, value any) error {
if len(names) == 0 {
return s.Set(value)
}
atoi, err := s.computeIndex(names[0])
if err != nil {
return err
}
if len(names) == 1 {
if value == nil {
if atoi >= 0 && atoi < s.value.Len() {
s.value.Set(reflect.AppendSlice(s.value.Slice(0, atoi), s.value.Slice(atoi+1, s.value.Len())))
}
return nil
}
if atoi > s.value.Len() {
x := reflect.MakeSlice(s.value.Type(), atoi-s.value.Len(), atoi-s.value.Len())
s.value.Set(reflect.AppendSlice(s.value, x))
s.value.Set(reflect.Append(s.value, reflect.ValueOf(value)))
} else if atoi == s.value.Len() {
s.value.Set(reflect.Append(s.value, reflect.ValueOf(value)))
} else {
s.value.Index(atoi).Set(reflect.ValueOf(value))
}
return nil
}
if atoi > s.value.Len() {
x := reflect.MakeSlice(s.value.Type(), atoi-s.value.Len()+1, atoi-s.value.Len()+1)
s.value.Set(reflect.AppendSlice(s.value, x))
} else if atoi == s.value.Len() {
s.value.Set(reflect.Append(s.value, reflect.Zero(s.value.Type().Elem())))
}
var writer Writer
writer, err = subWriter(s.value.Index(atoi))
if err != nil {
return err
}
s.mapWriters[atoi] = writer
return writer.linkSet(names[1:], value)
}
// can set struct.substruct field value
func (s *sliceImpl) linkGet(names []string) (any, bool) {
if len(names) == 0 {
return s.Get()
}
atoi, err := s.computeIndex(names[0])
if err != nil {
return nil, false
}
if atoi >= 0 && atoi < s.value.Len() {
writer, found := s.mapWriters[atoi]
if !found {
writer, err = subWriter(s.value.Index(atoi))
}
s.mapWriters[atoi] = writer
return writer.linkGet(names[1:])
}
return nil, false
}
func (s *sliceImpl) LinkSet(linkName string, value any) error {
return s.linkSet(strings.Split(linkName, SqliteSeq), value)
}
func (s *sliceImpl) LinkGet(linkName string) (any, bool) {
return s.linkGet(strings.Split(linkName, SqliteSeq))
}
func (s *sliceImpl) computeIndex(atoiStr string) (int, error) {
var atoi = -1
if len(s.sliceToMap) == 0 {
var err error
if atoiStr == "*" {
atoi = s.value.Len()
} else {
atoi, err = strconv.Atoi(atoiStr)
if err != nil {
return 0, err
}
}
} else {
var flag bool
for i := 0; i < s.value.Len(); i++ {
sub := fmt.Sprint(s.value.Index(i).FieldByName(s.sliceToMap).Interface())
if sub == atoiStr {
atoi = i
flag = true
break
}
}
if !flag {
atoi = s.value.Len()
}
}
return atoi, nil
}
func (s *sliceImpl) Type() reflect.Type {
return s.field.Type
}
func (s *sliceImpl) linkTyp(names []string) (reflect.Type, bool) {
if len(names) == 0 {
return s.Type(), true
}
ints := reflect.Zero(s.value.Type().Elem())
writer, err := subWriter(ints)
if err == nil {
return writer.linkTyp(names[1:])
}
return nil, false
}
func (s *sliceImpl) LinkTyp(linkName string) (reflect.Type, bool) {
return s.linkTyp(strings.Split(linkName, SqliteSeq))
}