[go: up one dir, main page]

nom 0.3.9

A byte oriented, zero copy, parser combinators library
Documentation
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