Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "Adapter between RxJava and ReactiveStreams"

dependencies {
compile 'io.reactivex:rxjava:1.0.+'
compile 'org.reactivestreams:reactive-streams:0.4.0.M1'
compile 'org.reactivestreams:reactive-streams:0.4.0.M2'
testCompile 'junit:junit-dep:4.10'
testCompile 'org.mockito:mockito-core:1.8.5'
}
Expand Down
31 changes: 29 additions & 2 deletions src/main/java/rx/RxReactiveStreams.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,48 @@
import rx.internal.PublisherObservableOnSubscribe;
import rx.internal.PublisherSubscriber;

/**
* The {@link RxReactiveStreams} helper class provides static utility methods to convert to and from
* {@link Observable}s and {@link Publisher}s.
*/
public class RxReactiveStreams {

/**
* Convert a Rx {@link Observable} into a Reactive Streams {@link Publisher}.
*
* @param observable the {@link Observable} to convert.
* @return the converted {@link Publisher}.
*/
public static <T> Publisher<T> toPublisher(Observable<T> observable) {
return new ObservablePublisher<T>(observable);
}

/**
* Convert a Reactive Streams {@link Publisher} into a Rx {@link Observable}.
*
* @param publisher the {@link Publisher} to convert.
* @return the converted {@link Observable}.
*/
public static <T> Observable<T> toObservable(final Publisher<T> publisher) {
return Observable.create(new PublisherObservableOnSubscribe<T>(publisher));
}

// Make subscriber contravariant after https://github.com/reactive-streams/reactive-streams/issues/104 is fixed
public static <T> void subscribe(Observable<T> observable, Subscriber<T> subscriber) {
/**
* Subscribe to the given Rx {@link Observable} with a Reactive Streams {@link Subscriber}.
*
* @param observable the {@link Observable} to subscribe to.
* @param subscriber the {@link Subscriber} which subscribes.
*/
public static <T> void subscribe(Observable<T> observable, Subscriber<? super T> subscriber) {
observable.subscribe(new ObservableSubscriber<T>(subscriber));
}

/**
* Subscribe to the given {@link Publisher} with a Rx {@link Subscriber}.
*
* @param publisher the {@link Publisher} to subscribe to.
* @param subscriber the {@link rx.Subscriber} which subscribes.
*/
public static <T> void subscribe(Publisher<T> publisher, rx.Subscriber<? super T> subscriber) {
publisher.subscribe(new PublisherSubscriber<T>(subscriber));
}
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/rx/internal/ObservablePublisher.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,28 @@
import rx.Observable;
import rx.RxReactiveStreams;

/**
* The {@link ObservablePublisher} wraps a Rx {@link Observable} and allows to subscribe to it with a Reactive Streams
* {@link Subscriber}.
*/
public class ObservablePublisher<T> implements Publisher<T> {

/**
* The wrapped Rx {@link Observable}.
*/
private final Observable<T> observable;

public ObservablePublisher(Observable<T> observable) {
/**
* Creates a new {@link ObservablePublisher}.
*
* @param observable the {@link Observable} to wrap.
*/
public ObservablePublisher(final Observable<T> observable) {
this.observable = observable;
}

@Override
public void subscribe(final Subscriber<T> s) {
public void subscribe(final Subscriber<? super T> s) {
RxReactiveStreams.subscribe(observable, s);
}

Expand Down
26 changes: 22 additions & 4 deletions src/main/java/rx/internal/ObservableSubscriber.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,37 @@

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import rx.Observable;

/**
* The {@link ObservableSubscriber} wraps a Reactive Streams {@link Subscriber} and allows to subscribe to a Rx
* {@link Observable}.
*
* This implementation properly forwards all emitted events and also handles subscriptions.
*/
public class ObservableSubscriber<T> extends rx.Subscriber<T> {
private final Subscriber<T> rsSubscriber;

public ObservableSubscriber(Subscriber<T> rsSubscriber) {
/**
* The wrapped Reactive Streams {@link Subscriber}.
*/
private final Subscriber<? super T> rsSubscriber;

/**
* Creates a new {@link ObservableSubscriber}.
*
* Note that because the Reactive Streams contract requires not sending anything until an explicit request is made,
* the {@link #request(long)} call is issued immediately.
*
* @param rsSubscriber the subscriber to wrap.
*/
public ObservableSubscriber(final Subscriber<? super T> rsSubscriber) {
this.rsSubscriber = rsSubscriber;

// Reactive streams contract requires not sending anything until an explict request is made
request(0);

rsSubscriber.onSubscribe(new Subscription() {
@Override
public void request(int n) {
public void request(long n) {
ObservableSubscriber.this.request(n);
}

Expand Down
14 changes: 13 additions & 1 deletion src/main/java/rx/internal/PublisherObservableOnSubscribe.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,23 @@
import rx.Observable;
import rx.RxReactiveStreams;

/**
* The {@link PublisherObservableOnSubscribe} wraps a Reactive Streams {@link Publisher} and allows to subscribe with
* a Rx {@link rx.Subscriber}.
*/
public class PublisherObservableOnSubscribe<T> implements Observable.OnSubscribe<T> {

/**
* The wrapped {@link Publisher}.
*/
private final Publisher<T> publisher;

public PublisherObservableOnSubscribe(Publisher<T> publisher) {
/**
* Creates a new {@link PublisherObservableOnSubscribe}.
*
* @param publisher the publisher where a Rx {@link rx.Subscriber} can subscribe.
*/
public PublisherObservableOnSubscribe(final Publisher<T> publisher) {
this.publisher = publisher;
}

Expand Down
40 changes: 24 additions & 16 deletions src/main/java/rx/internal/PublisherSubscriber.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
package rx.internal;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import rx.Producer;
import rx.functions.Action0;
import rx.subscriptions.Subscriptions;

/**
* Copyright 2014 Netflix, Inc.
*
Expand All @@ -21,9 +13,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rx.internal;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import rx.Producer;
import rx.functions.Action0;
import rx.subscriptions.Subscriptions;

/**
* The {@link PublisherSubscriber} wraps an Rx {@link rx.Subscriber} and forwards it all events from the corresponding
* {@link Subscriber}.
*
* Note that it also supports backpressure and subscription management.
*/
public class PublisherSubscriber<T> implements Subscriber<T> {

/**
* The wrapped Rx {@link rx.Subscriber}.
*/
private final rx.Subscriber<? super T> rxSubscriber;

/**
* Creates a new {@link PublisherSubscriber}.
*
* @param rxSubscriber the Rx {@link rx.Subscriber} that gets wrapped and notified.
*/
public PublisherSubscriber(rx.Subscriber<? super T> rxSubscriber) {
this.rxSubscriber = rxSubscriber;
}
Expand All @@ -33,14 +48,7 @@ public void onSubscribe(final Subscription rsSubscription) {
rxSubscriber.setProducer(new Producer() {
@Override
public void request(long n) {
// 0.4.0.M1 of reactive streams is bugged in that Subsription.request() takes an int
// https://github.com/reactive-streams/reactive-streams/issues/105
// MUST update this after that change
if (n <= Integer.MAX_VALUE) {
rsSubscription.request((int) n);
} else {
rsSubscription.request(Integer.MAX_VALUE);
}
rsSubscription.request(n);
}
});

Expand Down
20 changes: 10 additions & 10 deletions src/test/java/rx/test/IterablePublisher.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
package rx.test;

import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.util.Iterator;

/**
* Copyright 2014 Netflix, Inc.
*
Expand All @@ -21,6 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rx.test;

import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.util.Iterator;

public class IterablePublisher<T> implements Publisher<T> {

private final Iterable<T> iterable;
Expand All @@ -30,13 +30,13 @@ public IterablePublisher(Iterable<T> iterable) {
}

@Override
public void subscribe(final Subscriber<T> subscriber) {
public void subscribe(final Subscriber<? super T> subscriber) {
subscriber.onSubscribe(new Subscription() {

Iterator<T> iterator = iterable.iterator();

@Override
public void request(int n) {
public void request(long n) {
for (int i = 0; i < n; ++i) {
if (iterator.hasNext()) {
T next;
Expand Down