play.api.libs.iteratee.TraversableIteratee.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2009-2015 Typesafe Inc.
*/
package play.api.libs.iteratee
import play.api.libs.iteratee.Execution.Implicits.{ defaultExecutionContext => dec }
import scala.concurrent.{ ExecutionContext, Future }
/**
* @define paramEcSingle @param ec The context to execute the supplied function with. The context is prepared on the calling thread before being used.
*/
object Traversable {
/**
* A partially-applied function returned by the `head` method.
*/
trait Head[E] {
def apply[A](implicit p: E => scala.collection.TraversableLike[A, E]): Iteratee[E, Option[A]]
}
def head[E] = new Head[E] {
def apply[A](implicit p: E => scala.collection.TraversableLike[A, E]): Iteratee[E, Option[A]] = {
def step: K[E, Option[A]] = {
case Input.Empty => Cont(step)
case Input.EOF => Done(None, Input.EOF)
case Input.El(xs) if !xs.isEmpty => Done(Some(xs.head), Input.El(xs.tail))
case Input.El(empty) => Cont(step)
}
Cont(step)
}
}
def takeUpTo[M](count: Long)(implicit p: M => scala.collection.TraversableLike[_, M]): Enumeratee[M, M] = new Enumeratee[M, M] {
def applyOn[A](it: Iteratee[M, A]): Iteratee[M, Iteratee[M, A]] = {
def step(inner: Iteratee[M, A], leftToTake: Long)(in: Input[M]): Iteratee[M, Iteratee[M, A]] = {
in match {
case in @ Input.El(e) =>
inner.pureFlatFold {
case Step.Cont(k) if leftToTake < Int.MaxValue => e.splitAt(leftToTake.toInt) match {
case (all, x) if x.isEmpty => Cont(step(k(Input.El(all)), leftToTake - all.size))
case (x, left) if x.isEmpty => Done(inner, Input.El(left))
case (toPush, left) => Done(k(Input.El(toPush)), Input.El(left))
}
case Step.Cont(k) => Cont(step(k(Input.El(e)), leftToTake - e.size))
case _ => Done(inner, in)
}
case Input.EOF => Done(inner, Input.EOF)
case Input.Empty => Cont(step(inner, leftToTake))
}
}
Cont(step(it, count))
}
}
def take[M](count: Int)(implicit p: M => scala.collection.TraversableLike[_, M]): Enumeratee[M, M] = new Enumeratee[M, M] {
def applyOn[A](it: Iteratee[M, A]): Iteratee[M, Iteratee[M, A]] = {
def step(inner: Iteratee[M, A], leftToTake: Int)(in: Input[M]): Iteratee[M, Iteratee[M, A]] = {
in match {
case in @ Input.El(e) =>
e.splitAt(leftToTake) match {
case (all, x) if x.isEmpty => inner.pureFlatFold {
case Step.Done(_, _) => Cont(step(inner, (leftToTake - all.size)))
case Step.Cont(k) => Cont(step(k(Input.El(all)), (leftToTake - all.size)))
case Step.Error(_, _) => Cont(step(inner, (leftToTake - all.size)))
}
case (x, left) if x.isEmpty => Done(inner, Input.El(left))
case (toPush, left) => Done(inner.pureFlatFold { case Step.Cont(k) => k(Input.El(toPush)); case _ => inner }, Input.El(left))
}
case Input.EOF => Done(inner, Input.EOF)
case Input.Empty => Cont(step(inner, leftToTake))
}
}
Cont(step(it, count))
}
}
import Enumeratee.CheckDone
/**
* Splits a stream of traversable input elements on a predicate. Yields all input up until
* the predicate matches within an input element. The input following a match is unprocessed.
*
* @param p The predicate to split input on.
* $paramEcSingle
*/
def splitOnceAt[M, E](p: E => Boolean)(implicit traversableLike: M => scala.collection.TraversableLike[E, M], ec: ExecutionContext): Enumeratee[M, M] = new CheckDone[M, M] {
val pec = ec.prepare()
def step[A](k: K[M, A]): K[M, Iteratee[M, A]] = {
case in @ Input.El(e) =>
Iteratee.flatten(Future(e.span(p))(pec).map {
case (prefix, suffix) if suffix.isEmpty => new CheckDone[M, M] { def continue[A](k: K[M, A]) = Cont(step(k)) } &> k(Input.El(prefix))
case (prefix, suffix) => Done(if (prefix.isEmpty) Cont(k) else k(Input.El(prefix)), Input.El(suffix.drop(1)))
}(dec))
case Input.Empty =>
new CheckDone[M, M] { def continue[A](k: K[M, A]) = Cont(step(k)) } &> k(Input.Empty)
case Input.EOF => Done(Cont(k), Input.EOF)
}
def continue[A](k: K[M, A]) = Cont(step(k))
}
def drop[M](count: Int)(implicit p: M => scala.collection.TraversableLike[_, M]): Enumeratee[M, M] = new Enumeratee[M, M] {
def applyOn[A](inner: Iteratee[M, A]): Iteratee[M, Iteratee[M, A]] = {
def step(it: Iteratee[M, A], leftToDrop: Int)(in: Input[M]): Iteratee[M, Iteratee[M, A]] = {
in match {
case in @ Input.El(e) =>
val left = leftToDrop - e.size
left match {
case i if i > 0 => Cont(step(it, left))
case i =>
val toPass = if (i < 0) Input.El(e.drop(leftToDrop)) else Input.Empty
it.pureFlatFold {
case Step.Cont(k) => Enumeratee.passAlong.applyOn(k(toPass))
case _ => Done(it, toPass)
}
}
case Input.Empty => Cont(step(it, leftToDrop))
case Input.EOF => Done(it, Input.EOF)
}
}
Cont(step(inner, count))
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy