type Stream: list of chunks or EOF
type Iteratee:
* Done: does not read data anymore
* MoreData: calls again the step function (Cont state)
* msg to stream producer (rewinf, error, etc)
Enumerator: stream producer, apply iteratee to Stream
Enumeratee: can transform an enumerator or iteratee for use by an iteratee
https://github.com/playframework/playframework/blob/master/framework/src/iteratees/src/main/scala/play/api/libs/iteratee/Iteratee.scala
trait Iteratee[E, +A] (E input type, A result type)
def run: Future[A] = fold({
case Step.Done(a, _) => Future.successful(a)
case Step.Cont(k) => k(Input.EOF).fold({
case Step.Done(a1, _) => Future.successful(a1)
case Step.Cont(_) => sys.error("diverging iteratee after Input.EOF")
case Step.Error(msg, e) => sys.error(msg)
})(dec)
case Step.Error(msg, e) => sys.error(msg)
})(dec)
trait Enumerator[E] {
parent =>
def apply[A](i: Iteratee[E, A]): Future[Iteratee[E, A]]
#####################
Concept: a function (or struct or whatever) which takes a chunk of data as input, and the previous state (or is stuck in a loop blocking over a tx/rx)
and returns the updated state and the next function? What about tail call recursion?
that function can send a message to another task, and wait for an answer (interaction in parsing)
that function can tell the enumerator to rewind or seek
I want to chain iteratees
Let's say:
File or network
-> Byte reader Enumerator
asks the iteratee for how much data is needed (iteratee starts in MoreData state)
-> chunk to Iteratee (chunk is a reference to a slice of the input, an array of bytes)
Iteratee parses the chunk
can say done (and return data)
or want more data (the enumerator then calls it with a bigger slice, or the state is updated to include the current slice?)
or an error (recoverable?)
or a seeking message (I want the 2nd chunk, not the first!)
In a parser context: if one iteratee fails, we can try the next.
Then the iteratee can ask for just the header first, test it, and if not ok return an error