Skip to content

Instantly share code, notes, and snippets.

@negator
Last active December 10, 2015 02:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save negator/4366881 to your computer and use it in GitHub Desktop.
Save negator/4366881 to your computer and use it in GitHub Desktop.
The flattenEnumerator function, which converts an Enumerator of Enumerators into an Enumerator
/*
* Flatten an enumerator of enumerators of some type into an enumerator of some type
*/
def flatten[T](enumerator: Enumerator[Enumerator[T]]): Enumerator[T] = new Enumerator[T] {
def step[A](it: Iteratee[T, A])(in: Input[Enumerator[T]]): Iteratee[Enumerator[T], Iteratee[T, A]] = {
in match {
case Input.EOF => Done(Iteratee.flatten(it.feed(Input.EOF)), Input.EOF)
case Input.Empty => Cont(step(it))
case Input.El(e) => {
val promise = e |>> Cont(removeEof(it))
val next = Iteratee.flatten(promise.flatMap(_.run))
next.pureFlatFold(
(v, l) => Done(next, in),
(_) => Cont(step(next)),
(msg, input) => Error(msg, in))
}
}
}
def apply[A](it: Iteratee[T, A]): PlayPromise[Iteratee[T, A]] = {
it.fold(
(v, l) => PlayPromise pure it,
(_) => enumerator |>> Cont(step(it)) flatMap (_.run),
(msg, input) => PlayPromise pure it
)
}
}
/*Wrap the iteratee with an outer feeding iteratee, which does not feed EOF*/
def removeEof[A, T](inner: Iteratee[T, A])(el: Input[T]): Iteratee[T, Iteratee[T, A]] = {
el match {
case Input.Empty | Input.El(_) =>
inner.pureFlatFold (
(n, i) => Done(inner, Input.Empty),
k => Cont(removeEof(k(el))),
(m, i) => Error(m, i))
case Input.EOF => Done(inner, Input.Empty)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment