Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added unfoldM mapM and pals

  • Loading branch information...
commit e4c97e7a5a504309f16c6822c9694a011b81da62 1 parent d83e322
Sadek Drobi authored
View
98 framework/src/play/src/main/scala/play/api/libs/iteratee/Iteratee.scala
@@ -549,6 +549,28 @@ object Enumeratee {
}
}
+ def mapInputM[From] = new {
+ def apply[To](f: Input[From] => Promise[Input[To]]) = new CheckDone[From, To] {
+
+ def step[A](k: K[To, A]): K[From, Iteratee[To, A]] = {
+ case in @ (Input.El(_) | Input.Empty) =>
+ new CheckDone[From, To] { def continue[A](k: K[To, A]) = Cont(step(k)) } &> Iteratee.flatten(f(in).map(k(_)))
+
+ case Input.EOF => Done(Cont(k), Input.EOF)
+ }
+
+ def continue[A](k: K[To, A]) = Cont(step(k))
+ }
+ }
+
+ def mapM[E] = new {
+ def apply[NE](f: E => Promise[NE]): Enumeratee[E, NE] = mapInputM[E]{
+ case Input.Empty => Promise.pure(Input.Empty)
+ case Input.EOF => Promise.pure(Input.EOF)
+ case Input.El(e) => f(e).map(Input.El(_))
+ }
+ }
+
/**
* Create an Enumeratee which transforms its input using a given function
*/
@@ -742,6 +764,34 @@ object Enumeratee {
}
}
+
+ def passAlong[M] = new Enumeratee.CheckDone[M, M] {
+
+ def step[A](k: K[M, A]): K[M, Iteratee[M, A]] = {
+
+ case in @ (Input.El(_) | Input.Empty) => new Enumeratee.CheckDone[M, M] { def continue[A](k: K[M, A]) = Cont(step(k)) } &> k(in)
+
+ case Input.EOF => Done(Cont(k), Input.EOF)
+ }
+ def continue[A](k: K[M, A]) = Cont(step(k))
+ }
+
+ def onEOF[E](action: () => Unit):Enumeratee[E,E] = new CheckDone[E, E] {
+
+ def step[A](k: K[E, A]): K[E, Iteratee[E, A]] = {
+
+ case Input.EOF =>
+ action()
+ Done(Cont(k), Input.EOF)
+
+ case in =>
+ new CheckDone[E, E] { def continue[A](k: K[E, A]) = Cont(step(k)) } &> k(in)
+ }
+
+ def continue[A](k: K[E, A]) = Cont(step(k))
+
+ }
+
}
object Enumerator {
@@ -890,6 +940,44 @@ object Enumerator {
import scalax.io.JavaConverters._
+ def unfoldM[S,E](s:S)(f: S => Promise[Option[(S,E)]] ): Enumerator[E] = new Enumerator[E] {
+ def apply[A](it: Iteratee[E, A]): Promise[Iteratee[E, A]] = {
+
+ var iterateeP = Promise[Iteratee[E, A]]()
+
+ def step(it: Iteratee[E, A], state:S) {
+
+ val next = it.fold(
+ (a, e) => { iterateeP.redeem(it); Promise.pure(None) },
+ k => {
+ f(state).map {
+ case None => {
+ val remainingIteratee = k(Input.EOF)
+ iterateeP.redeem(remainingIteratee)
+ None
+ }
+ case Some((s,read)) => {
+ val nextIteratee = k(Input.El(read))
+ Some((nextIteratee,s))
+ }
+ }
+ },
+ (_, _) => { iterateeP.redeem(it); Promise.pure(None) }
+ )
+
+ next.extend1 {
+ case Redeemed(Some((i,s))) => step(i,s)
+ case Redeemed(None) => // do nothing, already redeemed
+ case Thrown(e) => iterateeP.throwing(e)
+ }
+
+ }
+
+ step(it, s)
+ iterateeP
+ }
+ }
+
def fromCallback1[E](retriever: Boolean => Promise[Option[E]],
onComplete: () => Unit = () => (),
onError: (String, Input[E]) => Unit = (_: String, _: Input[E]) => ()) = new Enumerator[E] {
@@ -919,14 +1007,12 @@ object Enumerator {
next.extend1 {
case Redeemed(Some(i)) => step(i)
- case Thrown(e) =>
+
+ case Redeemed(None) => onComplete()
+ case Thrown(e) =>
iterateeP.throwing(e)
- onComplete()
- case _ => throw new RuntimeException("should be either Redeemed or Thrown")
}
-
}
-
step(it, true)
iterateeP
}
@@ -961,6 +1047,8 @@ object Enumerator {
next.extend1 {
case Redeemed(Some(i)) => step(i)
+ case Thrown(e) =>
+ iterateeP.throwing(e)
case _ => onComplete()
}
View
1  framework/src/play/src/main/scala/play/api/libs/iteratee/TraversableIteratee.scala
@@ -36,7 +36,6 @@ object Traversable {
}
Cont(step(it, count))
-
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.