Skip to content

Commit

Permalink
Typed channels with FromChannelT (#90)
Browse files Browse the repository at this point in the history
* typed channel support

* renamed FromTypedChannel() to FromChannelT()

* fixed example name
  • Loading branch information
kalaninja authored Feb 24, 2020
1 parent 80a9834 commit 7a0b206
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ From(sentences).
## Release Notes

~~~
v3.0.2 (2020-02-23)
* Added FromChannelT().
v3.0.1 (2019-07-09)
* Support for Go modules
Expand Down
30 changes: 30 additions & 0 deletions benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,33 @@ func BenchmarkZipSkipTake_generics(b *testing.B) {
}).Skip(2).Take(5)
}
}

func BenchmarkFromChannel(b *testing.B) {
for n := 0; n < b.N; n++ {
ch := make(chan interface{})
go func() {
for i := 0; i < size; i++ {
ch <- i
}

close(ch)
}()

FromChannel(ch).All(func(i interface{}) bool { return true })
}
}

func BenchmarkFromChannelT(b *testing.B) {
for n := 0; n < b.N; n++ {
ch := make(chan interface{})
go func() {
for i := 0; i < size; i++ {
ch <- i
}

close(ch)
}()

FromChannelT(ch).All(func(i interface{}) bool { return true })
}
}
18 changes: 17 additions & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2509,7 +2509,7 @@ func ExampleQuery_WhereIndexedT() {
// [0 20 15 40]
}

// The following code example demonstrates how to use the Zip
// The following code example demonstrates how to use the ZipT
// method to merge two slices.
func ExampleQuery_ZipT() {
number := []int{1, 2, 3, 4, 5}
Expand All @@ -2524,3 +2524,19 @@ func ExampleQuery_ZipT() {
// Output:
// [[1 one] [2 two] [3 three]]
}

// The following code example demonstrates how to use the FromChannelT
// to make a Query from typed channel.
func ExampleFromChannelT() {
ch := make(chan string, 3)
ch <- "one"
ch <- "two"
ch <- "three"
close(ch)

q := FromChannelT(ch)

fmt.Println(q.Results())
// Output:
// [one two three]
}
23 changes: 22 additions & 1 deletion from.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ func From(source interface{}) Query {
case reflect.String:
return FromString(source.(string))
case reflect.Chan:
return FromChannel(source.(chan interface{}))
if _, ok := source.(chan interface{}); ok {
return FromChannel(source.(chan interface{}))
} else {
return FromChannelT(source)
}
default:
return FromIterable(source.(Iterable))
}
Expand All @@ -97,6 +101,23 @@ func FromChannel(source <-chan interface{}) Query {
}
}

// FromChannelT is the typed version of FromChannel.
//
// - source is of type "chan TSource"
//
// NOTE: FromChannel has better performance than FromChannelT.
func FromChannelT(source interface{}) Query {
src := reflect.ValueOf(source)
return Query{
Iterate: func() Iterator {
return func() (interface{}, bool) {
value, ok := src.Recv()
return value.Interface(), ok
}
},
}
}

// FromString initializes a linq query with passed string, linq iterates over
// runes of string.
func FromString(source string) Query {
Expand Down
21 changes: 21 additions & 0 deletions from_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ func TestFrom(t *testing.T) {
c <- 1
close(c)

ct := make(chan int, 3)
ct <- -10
ct <- 0
ct <- 10
close(ct)

tests := []struct {
input interface{}
output []interface{}
Expand All @@ -23,6 +29,7 @@ func TestFrom(t *testing.T) {
{map[string]bool{"foo": true}, []interface{}{KeyValue{"foo", true}}, true},
{map[string]bool{"foo": true}, []interface{}{KeyValue{"foo", false}}, false},
{c, []interface{}{-1, 0, 1}, true},
{ct, []interface{}{-10, 0, 10}, true},
{foo{f1: 1, f2: true, f3: "string"}, []interface{}{1, true, "string"}, true},
}

Expand Down Expand Up @@ -51,6 +58,20 @@ func TestFromChannel(t *testing.T) {
}
}

func TestFromChannelT(t *testing.T) {
c := make(chan int, 3)
c <- 10
c <- 15
c <- -3
close(c)

w := []interface{}{10, 15, -3}

if q := FromChannelT(c); !validateQuery(q, w) {
t.Errorf("FromChannelT() failed expected %v", w)
}
}

func TestFromString(t *testing.T) {
s := "string"
w := []interface{}{'s', 't', 'r', 'i', 'n', 'g'}
Expand Down

0 comments on commit 7a0b206

Please sign in to comment.