// Consume fetches the values. s is a Stream of T. func (pb *PageBuffer) Consume(s functional.Stream) (err error) { pb.page_no = 0 pb.idx = 0 pb.is_end = false for err == nil && !pb.isDesiredPageRead() { if pb.idx > 0 { pb.page_no++ } offset := pb.pageOffset(pb.page_no) pb.idx, err = readStreamIntoSlice( s, pb.buffer.Slice(offset, offset+pb.pageLen), pb.handler) } if err == nil { anElement := pb.buffer.Index(pb.pageOffset(pb.page_no + 1)) pb.handler.ensureValid(anElement) pb.is_end = s.Next(pb.handler.toInterface(anElement)) == functional.Done } else if err == functional.Done { pb.is_end = true err = nil if pb.page_no > 0 && pb.idx == 0 { pb.page_no-- pb.idx = pb.pageLen } } return }
// FirstOnly reads the first value from stream storing it in ptr. // FirstOnly returns emptyError if no values were on stream. func FirstOnly(stream functional.Stream, emptyError error, ptr interface{}) (err error) { err = stream.Next(ptr) if err == functional.Done { err = emptyError return } return }
func verifyTimes(t *testing.T, s functional.Stream, expectedTimes ...time.Time) { var actual time.Time for _, expected := range expectedTimes { if s.Next(&actual) != nil { t.Error("Stream too short.") return } if actual != expected { t.Errorf("Expected %v, got %v", expected, actual) } } if s.Next(&actual) != functional.Done { t.Error("Stream too long.") } }
func readStreamIntoSlice( s functional.Stream, aSlice reflect.Value, handler elementHandler) (numRead int, err error) { l := aSlice.Len() for numRead = 0; numRead < l; numRead++ { anElement := aSlice.Index(numRead) handler.ensureValid(anElement) err = s.Next(handler.toInterface(anElement)) if err != nil { break } } return }
// ByYear takes a Stream of DateCount instances and returns a Stream of // YearCount instances by totaling the counts in the DateCount instances // by year. The DateCount instances must be ordered by Date. Caller must Close // the returned Stream. Calling Close on returned Stream also closes s. func ByYear(s functional.Stream) functional.Stream { return functional.NewGenerator(func(e functional.Emitter) error { var ptr interface{} var opened bool var incoming DateCount // As soon as caller calls Close() we quit without pulling unnecessary // values from underlying stream. if ptr, opened = e.EmitPtr(); !opened { return s.Close() } var err error // We get the first date while propagating any errors to the caller. // Note that we stay in this loop until either we get a first date or // caller calls Close() for err = s.Next(&incoming); err != nil; err = s.Next(&incoming) { // Propagate error and yield execution to caller. Then get the next // pointer caller pases to Next(). if ptr, opened = e.Return(err); !opened { return s.Close() } } currentYear := incoming.Date.Year() // Running total for current year sum := incoming.Count // When Done marker is reached, we have to emit the count of the final year. for err = s.Next(&incoming); err != functional.Done; err = s.Next(&incoming) { // Propagate any errors to caller. if err != nil { if ptr, opened = e.Return(err); !opened { return s.Close() } continue } year := incoming.Date.Year() // If year changed, emit the count for the current year. // Then change currentYear and and make sum be the running total for // that year. if year != currentYear { *ptr.(*YearCount) = YearCount{Year: currentYear, Count: sum} if ptr, opened = e.Return(nil); !opened { return s.Close() } sum = incoming.Count currentYear = year } else { sum += incoming.Count } } // Emit the final year. *ptr.(*YearCount) = YearCount{Year: currentYear, Count: sum} // Note that we return nil, not functional.Done, since we are emitting the // count for the final year. The call to WaitForClose() takes // care of returning functional.Done to the caller until the caller calls // Close() e.Return(nil) functional.WaitForClose(e) return s.Close() }) }