-
Notifications
You must be signed in to change notification settings - Fork 2
/
mapper.go
151 lines (123 loc) · 3.57 KB
/
mapper.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
151
package mapper
import (
"context"
"fmt"
"reflect"
)
/***************************
@author: tiansheng.ren
@date: 2022/10/24
@desc:
***************************/
var (
mapperCV *defaultCopyValue
allMapperCV *defaultCopyValue
)
func init() {
mapperCV = newCopyValue()
allMapperCV = newCopyValue()
allMapperCV.structCache.copyPrivate = true
}
func Mapper(ctx context.Context, src, dst interface{}) error {
return mapperHandler(ctx, mapperCV, src, dst)
}
func AllMapper(ctx context.Context, src, dst interface{}) error {
return mapperHandler(ctx, allMapperCV, src, dst)
}
func ObjectsField(ctx context.Context, field, src, dst interface{}) error {
return mapperCV.ToSliceCopyValue(ctx, reflect.ValueOf(field), reflect.ValueOf(src), reflect.ValueOf(dst).Elem())
}
func MapKeys(ctx context.Context, src, dst interface{}) error {
return mapperCV.MapKeyToSliceCopyValue(ctx, reflect.ValueOf(src), reflect.ValueOf(dst).Elem())
}
func MapValues(ctx context.Context, src, dst interface{}) error {
return mapperCV.MapValueToSliceCopyValue(ctx, reflect.ValueOf(src), reflect.ValueOf(dst).Elem())
}
func Merge(ctx context.Context, srcList []interface{}, dst interface{}) error {
for _, src := range srcList {
if err := mapperHandler(ctx, mapperCV, src, dst); err != nil {
return err
}
}
return nil
}
func AllMerge(ctx context.Context, srcList []interface{}, dst interface{}) error {
for _, src := range srcList {
if err := mapperHandler(ctx, allMapperCV, src, dst); err != nil {
return err
}
}
return nil
}
func Chunk(ctx context.Context, src, dst interface{}, size int) error {
dstV := reflect.ValueOf(dst)
if dstV.Kind() != reflect.Ptr {
return fmt.Errorf("copy to object must be pointer")
}
dstV = dstV.Elem()
if !dstV.CanSet() {
return fmt.Errorf("copy to object must be can set")
}
srcV := reflect.ValueOf(src)
return mapperCV.SliceChunk(ctx, srcV, dstV, size)
}
func mapperHandler(ctx context.Context, dcv *defaultCopyValue, src, dst interface{}) error {
dstV := reflect.ValueOf(dst)
if dstV.Kind() != reflect.Ptr {
return fmt.Errorf("copy to object must be pointer")
}
srcV := reflect.ValueOf(src)
if dstV.Elem().Kind() == reflect.Invalid {
if srcV.Kind() == reflect.Invalid {
return nil
}
return fmt.Errorf("copy to object is nil")
}
if srcV.Kind() == reflect.Invalid || srcV.Kind() == reflect.Interface && srcV.IsValid() {
return nil
}
if !dstV.Elem().CanSet() {
return CopyValueError{Name: "mapper", Kinds: []reflect.Kind{reflect.Bool}, Received: dstV}
}
// support: type interface{}|struct result is struct
rawDstV := dstV.Elem()
if rawDstV.Kind() != reflect.Invalid {
for ; rawDstV.Kind() == reflect.Interface; rawDstV = rawDstV.Elem() {
}
if rawDstV.Kind() == reflect.Ptr {
dstV = rawDstV
}
}
dstV = dstV.Elem()
fn, err := dcv.lookupCopyValue(dstV)
if err != nil {
return err
}
if err := fn(ctx, srcV, dstV); err != nil {
return err
}
return nil
}
type mapper interface {
Mapper(ctx context.Context, src, dst interface{}) error
}
func NewMapper(options ...Option) mapper {
option := mergeOption(options...)
handler := newCopyValue()
if option.copyPrivate != nil {
handler.structCache.validateStruct = *option.copyPrivate
}
if option.validateStruct != nil && *option.validateStruct == true {
// Notice: copy tag change, here need change
handler.validate = newValidateStruct()
}
return &mapperInstance{
cv: handler,
}
}
type mapperInstance struct {
cv *defaultCopyValue
}
func (m mapperInstance) Mapper(ctx context.Context, src, dst interface{}) error {
return mapperHandler(ctx, m.cv, src, dst)
}