-
Notifications
You must be signed in to change notification settings - Fork 4
/
routes.go
115 lines (108 loc) · 3.5 KB
/
routes.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
package gomapper
import (
"fmt"
"reflect"
)
var routes = map[reflect.Type]map[reflect.Type]func(source interface{}, dest interface{}) error{}
func addSliceRoute[TSliceSource any, TSliceDest any](sliceMapFunc func(sourceSlice TSliceSource, destSlice TSliceDest) error) {
funcConverted := func(source any, dest any) error {
return sliceMapFunc(source.(TSliceSource), dest.(TSliceDest))
}
sourceSlice := *new(TSliceSource)
destSlice := *new(TSliceDest)
var route map[reflect.Type]func(source interface{}, dest interface{}) error
var ok bool
if route, ok = routes[reflect.TypeOf(sourceSlice)]; !ok {
route = map[reflect.Type]func(source interface{}, dest interface{}) error{}
routes[reflect.TypeOf(sourceSlice)] = route
}
route[reflect.TypeOf(destSlice)] = funcConverted
}
func addSliceRoutes[TSource, TDest any]() {
//source slice is a value, dest slice is a pointer
addSliceRoute(func(sourceSlice []TSource, pointerDestSlice *[]TDest) error {
if len(sourceSlice) == 0 {
*pointerDestSlice = make([]TDest, 0)
}
for _, source := range sourceSlice {
dest, err := MapTo[TDest](source)
if err != nil {
return err
}
*pointerDestSlice = append(*pointerDestSlice, dest)
}
return nil
})
//source slice is a value, dest slice is a pointer with pointer elements
addSliceRoute(func(sourceSlice []TSource, pointerDestSlice *[]*TDest) error {
if len(sourceSlice) == 0 {
*pointerDestSlice = make([]*TDest, 0)
}
for _, source := range sourceSlice {
dest, err := MapTo[TDest](source)
if err != nil {
return err
}
*pointerDestSlice = append(*pointerDestSlice, &dest)
}
return nil
})
//source slice is a value, dest slice is a pointer
addSliceRoute(func(sourceSlice []*TSource, pointerDestSlice *[]TDest) error {
if len(sourceSlice) == 0 {
*pointerDestSlice = make([]TDest, 0)
}
for _, source := range sourceSlice {
dest, err := MapTo[TDest](source)
if err != nil {
return err
}
*pointerDestSlice = append(*pointerDestSlice, dest)
}
return nil
})
addSliceRoute(func(sourceSlice []*TSource, pointerDestSlice *[]*TDest) error {
if len(sourceSlice) == 0 {
*pointerDestSlice = make([]*TDest, 0)
}
for _, source := range sourceSlice {
dest, err := MapTo[TDest](source)
if err != nil {
return err
}
*pointerDestSlice = append(*pointerDestSlice, &dest)
}
return nil
})
}
func addRoute[TSource, TDest any | []any](mapFunc func(source TSource, dest *TDest) error) error {
source := *new(TSource)
dest := *new(TDest)
sourceValueOf := reflect.ValueOf(source)
if sourceValueOf.Kind() == reflect.Ptr {
return fmt.Errorf("source type can't be reference type, route: %s -> %s", getTypeName(source), getTypeName(dest))
}
var route map[reflect.Type]func(source interface{}, dest interface{}) error
route, ok := routes[reflect.TypeOf(source)]
if !ok {
route = map[reflect.Type]func(source interface{}, dest interface{}) error{}
routes[reflect.TypeOf(source)] = route
}
funcConverted := func(source any, dest any) error {
sourceValueOf := reflect.ValueOf(source)
for sourceValueOf.Kind() == reflect.Ptr {
if sourceValueOf.IsNil() {
return nil
}
sourceValueOf = sourceValueOf.Elem()
}
return mapFunc(sourceValueOf.Interface().(TSource), dest.(*TDest))
}
route[reflect.TypeOf(&dest)] = funcConverted
// source is value, dest is ptr - its important
addSliceRoutes[TSource, TDest]()
return nil
}
func AddRoute[TSource, TDest any | []any](mapFunc func(source TSource, dest *TDest) error) error {
return addRoute[TSource, TDest](mapFunc)
}