-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfrom.go
150 lines (129 loc) · 3.11 KB
/
from.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 gostream
import (
"reflect"
)
// Iterator is an alias for function to iterate over data.
type Iterator func() (item interface{}, ok bool)
// Stream is the type returned from query functions. It can be iterated manually
// as shown in the example.
type Stream struct {
Iterate func() Iterator
}
// KeyValue ...
type KeyValue struct {
Key interface{}
Value interface{}
}
// Iterable ...
type Iterable interface {
Iterate() Iterator
}
// From initializes a Stream with passed slice, array or map as the source.
// String, channel or struct implementing Iterable interface can be used as an
// input. In this case From delegates it to FromString, FromChannel and
// FromIterable internally.
func From(source interface{}) Stream {
src := reflect.ValueOf(source)
switch src.Kind() {
case reflect.Slice, reflect.Array:
len := src.Len()
return Stream{
Iterate: func() Iterator {
index := 0
return func() (item interface{}, ok bool) {
ok = index < len
if ok {
item = src.Index(index).Interface()
index++
}
return
}
},
}
case reflect.Map:
len := src.Len()
return Stream{
Iterate: func() Iterator {
index := 0
keys := src.MapKeys()
return func() (item interface{}, ok bool) {
ok = index < len
if ok {
key := keys[index]
item = KeyValue{
Key: key.Interface(),
Value: src.MapIndex(key).Interface(),
}
index++
}
return
}
},
}
case reflect.String:
return FromString(source.(string))
case reflect.Chan:
if _, ok := source.(chan interface{}); ok {
return FromChannel(source.(chan interface{}))
} else {
return FromChannelT(source)
}
default:
return FromIterable(source.(Iterable))
}
}
// FromChannel initializes a Stream with passed channel, gostream iterates over
// channel until it is closed.
func FromChannel(source <-chan interface{}) Stream {
return Stream{
Iterate: func() Iterator {
return func() (item interface{}, ok bool) {
item, ok = <-source
return
}
},
}
}
// FromChannelT is the typed version of FromChannel.
//
// - source is of type "chan TSource"
//
// NOTE: FromChannel has better performance than FromChannelT.
func FromChannelT(source interface{}) Stream {
src := reflect.ValueOf(source)
return Stream{
Iterate: func() Iterator {
return func() (interface{}, bool) {
value, ok := src.Recv()
return value.Interface(), ok
}
},
}
}
// FromString initializes a Stream with passed string, gostream iterates over
// runes of string.
func FromString(source string) Stream {
runes := []rune(source)
len := len(runes)
return Stream{
Iterate: func() Iterator {
index := 0
return func() (item interface{}, ok bool) {
ok = index < len
if ok {
item = runes[index]
index++
}
return
}
},
}
}
// FromIterable initializes a Stream with custom collection passed. This
// collection has to implement Iterable interface, gostream iterates over items,
// that has to implement Comparable interface or be basic types.
func FromIterable(source Iterable) Stream {
return Stream{
Iterate: source.Iterate,
}
}