/
ReadAheadIterator.scala
51 lines (42 loc) · 1.03 KB
/
ReadAheadIterator.scala
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
package slick.util
/**
* An iterator on top of a data source which does not offer a hasNext()
* method without doing a next()
*/
trait ReadAheadIterator[+T] extends BufferedIterator[T] {
private[this] var state = 0 // 0: no data, 1: cached, 2: finished
private[this] var cached: T = null.asInstanceOf[T]
protected[this] final def finished(): T = {
state = 2
null.asInstanceOf[T]
}
/** Return a new value or call finished() */
protected def fetchNext(): T
def head: T = {
update()
if(state == 1) cached
else throw new NoSuchElementException("head on empty iterator")
}
def headOption: Option[T] = {
update()
if(state == 1) Some(cached)
else None
}
private[this] def update() {
if(state == 0) {
cached = fetchNext()
if(state == 0) state = 1
}
}
def hasNext: Boolean = {
update()
state == 1
}
def next(): T = {
update()
if(state == 1) {
state = 0
cached
} else throw new NoSuchElementException("next on empty iterator");
}
}