All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaz.stream.sink.scala Maven / Gradle / Ivy

The newest version!
package scalaz.stream

import scalaz.Functor
import scalaz.concurrent.Task
import scalaz.stream.Process.{Emit, Halt, Step}
import scalaz.syntax.functor._

object sink {

  /** Promote an effectful function to a `Sink`. */
  def lift[F[_], A](f: A => F[Unit]): Sink[F, A] = channel lift f

}

final class SinkSyntax[F[_], I](val self: Sink[F, I]) extends AnyVal {

  /** Converts `Sink` to `Channel`, that will perform the side effect and echo its input. */
  def toChannel(implicit F: Functor[F]): Channel[F, I, I] =
    self.map(f => (i: I) => f(i).as(i))
}

final class SinkTaskSyntax[I](val self: Sink[Task, I]) extends AnyVal {

  /** converts sink to sink that first pipes received `I0` to supplied p1 */
  def pipeIn[I0](p1: Process1[I0, I]): Sink[Task, I0] = Process.suspend {
    import scalaz.Scalaz._
    // Note: Function `f` from sink `self` may be used for more than 1 element emitted by `p1`.
    @volatile var cur = p1.step
    @volatile var lastF: Option[I => Task[Unit]] = None
    self.takeWhile { _ =>
      cur match {
        case Halt(Cause.End) => false
        case Halt(cause)     => throw new Cause.Terminated(cause)
        case _               => true
      }
    } map { (f: I => Task[Unit]) =>
      lastF = f.some
      (i0: I0) => Task.suspend {
        cur match {
          case Halt(_) => sys.error("Impossible")
          case Step(Emit(piped), cont) =>
            cur = process1.feed1(i0) { cont.continue }.step
            piped.toList.traverse_(f)
          case Step(hd, cont) =>
            val (piped, tl) = process1.feed1(i0)(hd +: cont).unemit
            cur = tl.step
            piped.toList.traverse_(f)
        }
      }
    } onHalt {
      case Cause.Kill =>
        lastF map { f =>
          cur match {
            case Halt(_) => sys.error("Impossible (2)")
            case s@Step(_, _) =>
              s.toProcess.disconnect(Cause.Kill).evalMap(f).drain
          }
        } getOrElse Halt(Cause.Kill)
      case Cause.End  => Process.halt
      case [email protected](_) => Process.halt.causedBy(c)
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy