-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTest.scala
140 lines (118 loc) · 4.89 KB
/
Test.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package test
import rx.lang.scala._
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext,Await,future,Future,Promise}
import scala.util.{Try,Success,Failure}
import play.api.libs.iteratee._
import play.api.libs.iteratee.Concurrent.Channel
import java.io.File
import Enumerator.Pushee
import ExecutionContext.Implicits.global
object Test extends App {
import RxPlay._
// /* Running fold iteratee on observer */
val observer = Observable(1, 2, 3, 4, 5)
val res = observer.run(Iteratee.fold(0) { (total, elt) => total + elt })
println(Await.result(res, 5 seconds))
// /* Using Enumerator created from file as an observer */
val fileEnum = Enumerator.fromFile(new File("test.txt"), 1)
val fileObs: Observable[Array[Byte]] = fileEnum
fileObs.map(new String(_)).subscribe(println(_))
// Using implicit conversion to apply composed enumeratees and iteratee to async observable
val filterOdd = Enumeratee.filter[Long](_ % 2 != 0)
val takeFive = Enumeratee.take[Long](5)
val longToString = Enumeratee.map[Long](_.toString)
val composed = filterOdd compose takeFive compose longToString
val asyncIntObserverable = Observable.interval(50 millis)
asyncIntObserverable through composed run Iteratee.foreach(println(_))
}
object RxPlay {
implicit def enumerator2Observable[T](enum: Enumerator[T]): Observable[T] = {
Observable({ observer: Observer[T] =>
var cancelled = false
val cancellableEnum = enum through Enumeratee.breakE[T](_ => cancelled)
cancellableEnum (
Iteratee.foreach(observer.onNext(_))
).onComplete {
case Success(_) => observer.onCompleted()
case Failure(e) => observer.onError(e)
}
new Subscription { override def unsubscribe() = { cancelled = true } }
})
}
implicit def observable2Enumerator[T](obs: Observable[T]): Enumerator[T] = {
unicast[T] { (chan) =>
val subscription = obs.subscribe(new ChannelObserver(chan))
val onComplete = { () => subscription.unsubscribe }
val onError = { (_: String, _: Input[T]) => subscription.unsubscribe }
(onComplete, onError)
}
}
class ChannelObserver[T](chan: Channel[T]) extends rx.Observer[T] {
def onNext(arg: T): Unit = chan.push(arg)
def onCompleted(): Unit = chan.end()
def onError(e: Throwable): Unit = chan.end(e)
}
def unicast[E] (onStart: Channel[E] => (() => Unit, (String, Input[E]) => Unit)) = new Enumerator[E] {
import scala.concurrent.stm.Ref
def apply[A](it: Iteratee[E, A]): Future[Iteratee[E, A]] = {
val promise: scala.concurrent.Promise[Iteratee[E, A]] = Promise[Iteratee[E, A]]()
val iteratee: Ref[Future[Option[Input[E] => Iteratee[E, A]]]] = Ref(it.pureFold { case Step.Cont(k) => Some(k); case other => promise.success(other.it); None})
val onCompletePromise: scala.concurrent.Promise[() => Unit] = Promise[() => Unit]()
val onErrorPromise: scala.concurrent.Promise[(String, Input[E]) => Unit] = Promise[(String, Input[E]) => Unit]()
val pushee = new Channel[E] {
def close() {
iteratee.single.swap(Future.successful(None)).onComplete{
case Success(maybeK) => maybeK.foreach { k =>
promise.success(k(Input.EOF))
}
case Failure(e) => promise.failure(e)
}
}
def end(e: Throwable) {
iteratee.single.swap(Future.successful(None)).onComplete {
case Success(maybeK) =>
maybeK.foreach(_ => promise.failure(e))
case Failure(e) => promise.failure(e)
}
}
def end() {
iteratee.single.swap(Future.successful(None)).onComplete { maybeK =>
maybeK.get.foreach(k => promise.success(Cont(k)))
}
}
def push(item: Input[E]) {
val eventuallyNext = Promise[Option[Input[E] => Iteratee[E,A]]]()
iteratee.single.swap(eventuallyNext.future).onComplete {
case Success(None) => eventuallyNext.success(None)
case Success(Some(k)) =>
val n = {
val next = k(item)
next.pureFold {
case Step.Done(a, in) => {
onCompletePromise.future.foreach(_())
promise.success(next)
None
}
case Step.Error(msg, e) =>
onErrorPromise.future.foreach(_(msg, e))
promise.success(next)
None
case Step.Cont(k) =>
Some(k)
}
}
eventuallyNext.completeWith(n)
case Failure(e) =>
promise.failure(e)
eventuallyNext.success(None)
}
}
}
val (onComplete, onError) = onStart(pushee)
onCompletePromise.success(onComplete)
onErrorPromise.success(onError)
promise.future
}
}
}