File: builder.go

package info (click to toggle)
golang-github-thoas-go-funk 0.9.3-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 504 kB
  • sloc: makefile: 10
file content (110 lines) | stat: -rw-r--r-- 3,349 bytes parent folder | download
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
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
}