-
Notifications
You must be signed in to change notification settings - Fork 273
/
builder.go
109 lines (95 loc) · 3.27 KB
/
builder.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
package funk
import (
"fmt"
"reflect"
)
// Builder contains all tools which can be chained.
type Builder interface {
Chunk(size int) Builder
Compact() Builder
Drop(n int) Builder
Filter(predicate interface{}) Builder
Flatten() Builder
FlattenDeep() Builder
Initial() Builder
Intersect(y interface{}) Builder
Join(rarr interface{}, fnc JoinFnc) Builder
Map(mapFunc interface{}) Builder
FlatMap(mapFunc interface{}) Builder
Reverse() Builder
Shuffle() Builder
Tail() Builder
Uniq() Builder
Without(values ...interface{}) Builder
All() bool
Any() bool
Contains(elem interface{}) bool
Every(elements ...interface{}) bool
Find(predicate interface{}) interface{}
ForEach(predicate interface{})
ForEachRight(predicate interface{})
Head() interface{}
Keys() interface{}
IndexOf(elem interface{}) int
IsEmpty() bool
Last() interface{}
LastIndexOf(elem interface{}) int
NotEmpty() bool
Product() float64
Reduce(reduceFunc, acc interface{}) interface{}
Sum() float64
Type() reflect.Type
Value() interface{}
Values() interface{}
}
// Chain creates a simple new go-funk.Builder from a collection. Each method
// call generate a new builder containing the previous result.
func Chain(v interface{}) Builder {
isNotNil(v, "Chain")
valueType := reflect.TypeOf(v)
if isValidBuilderEntry(valueType) ||
(valueType.Kind() == reflect.Ptr && isValidBuilderEntry(valueType.Elem())) {
return &chainBuilder{v}
}
panic(fmt.Sprintf("Type %s is not supported by Chain", valueType.String()))
}
// LazyChain creates a lazy go-funk.Builder from a collection. Each method call
// generate a new builder containing a method generating the previous value.
// With that, all data are only generated when we call a tailling method like All or Find.
func LazyChain(v interface{}) Builder {
isNotNil(v, "LazyChain")
valueType := reflect.TypeOf(v)
if isValidBuilderEntry(valueType) ||
(valueType.Kind() == reflect.Ptr && isValidBuilderEntry(valueType.Elem())) {
return &lazyBuilder{func() interface{} { return v }}
}
panic(fmt.Sprintf("Type %s is not supported by LazyChain", valueType.String()))
}
// LazyChainWith creates a lazy go-funk.Builder from a generator. Like LazyChain, each
// method call generate a new builder containing a method generating the previous value.
// But, instead of using a collection, it takes a generator which can generate values.
// With LazyChainWith, to can create a generic pipeline of collection transformation and,
// throw the generator, sending different collection.
func LazyChainWith(generator func() interface{}) Builder {
isNotNil(generator, "LazyChainWith")
return &lazyBuilder{func() interface{} {
isNotNil(generator, "LazyChainWith")
v := generator()
valueType := reflect.TypeOf(v)
if isValidBuilderEntry(valueType) ||
(valueType.Kind() == reflect.Ptr && isValidBuilderEntry(valueType.Elem())) {
return v
}
panic(fmt.Sprintf("Type %s is not supported by LazyChainWith generator", valueType.String()))
}}
}
func isNotNil(v interface{}, from string) {
if v == nil {
panic(fmt.Sprintf("nil value is not supported by %s", from))
}
}
func isValidBuilderEntry(valueType reflect.Type) bool {
return valueType.Kind() == reflect.Slice || valueType.Kind() == reflect.Array ||
valueType.Kind() == reflect.Map ||
valueType.Kind() == reflect.String
}