Skip to content

Commit

Permalink
Add RxJava 3 extensions (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bencodes authored Jun 26, 2020
1 parent e03621f commit 868bab7
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 3 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> We don't think that Kotlin itself needs `Optional` because it has strong
> `null`-safe type system that effectively eliminates need in such a wrapper.
> However there are Java APIs and libraries like [RxJava 2][rxjava2] which don't accept `null` values
> However there are Java APIs and libraries like [RxJava 2][rxjava2] and [RxJava 3][rxjava3] which don't accept `null` values
> and language-level nullability cannot help with that.
> We also think that in many cases you can use `sealed class`es to express absent values,
Expand Down Expand Up @@ -65,7 +65,7 @@ val (value) = optional

Use the static `Optional.toOptional()` to wrap an instance of `T` into `Optional<T>`.

### RxJava 2 Extensions
### RxJava Extensions

```kotlin
val values = Observable.just(Some("a"), None, Some("b"))
Expand Down Expand Up @@ -112,6 +112,12 @@ implementation "com.gojuno.koptional:koptional:$koptional_version"
implementation "com.gojuno.koptional:koptional-rxjava2-extensions:$koptional_version"
```

### [RxJava 3][rxjava3] Extensions

```groovy
implementation "com.gojuno.koptional:koptional-rxjava3-extensions:$koptional_version"
```

### [Reactor](https://projectreactor.io/) Extensions

```groovy
Expand All @@ -137,4 +143,5 @@ See the License for the specific language governing permissions and
limitations under the License.
```

[rxjava2]: https://github.com/ReactiveX/RxJava/
[rxjava2]: https://github.com/ReactiveX/RxJava/tree/2.x
[rxjava3]: https://github.com/ReactiveX/RxJava/tree/3.x
3 changes: 3 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ext.versions = [
kotlin : '1.2.41',
rxJava2 : '2.2.19',
rxJava3 : '3.0.4',
reactor : '3.0.7.RELEASE',

junit : '4.12',
Expand All @@ -12,11 +13,13 @@ ext.versions = [
ext.libraries = [
koptional : project(':koptional'),
koptionalRxJava2Extensions: project(':koptional-rxjava2-extensions'),
koptionalRxJava3Extensions: project(':koptional-rxjava3-extensions'),

kotlinStd : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlin",
kotlinRuntime : "org.jetbrains.kotlin:kotlin-runtime:$versions.kotlin",
kotlinReflect : "org.jetbrains.kotlin:kotlin-reflect:$versions.kotlin",
rxJava2 : "io.reactivex.rxjava2:rxjava:$versions.rxJava2",
rxJava3 : "io.reactivex.rxjava3:rxjava:$versions.rxJava3",
reactor : "io.projectreactor:reactor-core:$versions.reactor",
reactorTest : "io.projectreactor.addons:reactor-test:$versions.reactor",

Expand Down
25 changes: 25 additions & 0 deletions koptional-rxjava3-extensions/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apply plugin: 'kotlin'
apply plugin: 'org.junit.platform.gradle.plugin'
apply from: '../gradle/publishing.gradle'

dependencies {
compile libraries.koptional
compile libraries.rxJava3
}

dependencies {
testCompile libraries.spek
testCompile libraries.spekJunitPlatformEngine
testCompile libraries.assertJ
testCompile libraries.junitPlatformLauncher
}

junitPlatform {
platformVersion = versions.junitPlatform

filters {
engines {
include 'spek'
}
}
}
1 change: 1 addition & 0 deletions koptional-rxjava3-extensions/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
description=Extensions to work with Optional in RxJava3 streams.
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.gojuno.koptional.rxjava3

import com.gojuno.koptional.None
import com.gojuno.koptional.Optional
import com.gojuno.koptional.Some
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single

private inline fun <reified R : Any> Observable<*>.ofType(): Observable<R> = ofType(R::class.java)
private inline fun <reified R : Any> Flowable<*>.ofType(): Flowable<R> = ofType(R::class.java)
private inline fun <reified R : Any> Maybe<*>.ofType(): Maybe<R> = ofType(R::class.java)
private inline fun <reified R : Any> Single<*>.ofType(): Maybe<R> = filter { it is R }.cast(R::class.java)

/**
* Filters items emitted by an ObservableSource by only emitting those that are `Some`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Observable that emits `Some.value` of those items emitted by the source ObservableSource that are `Some`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Observable<out Optional<T>>.filterSome(): Observable<T> = ofType<Some<T>>().map { it.value }

/**
* Filters items emitted by a Publisher by only emitting those that are `Some`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Flowable that emits `Some.value` of those items emitted by the source Publisher that are `Some`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Flowable<out Optional<T>>.filterSome(): Flowable<T> = ofType<Some<T>>().map { it.value }

/**
* Filters items emitted by an MaybeSource by only emitting those that are `Some`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Maybe that emits `Some.value` of those items emitted by the source MaybeSource that are `Some`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Maybe<out Optional<T>>.filterSome(): Maybe<T> = ofType<Some<T>>().map { it.value }

/**
* Filters items emitted by an SingleSource by only emitting those that are `Some`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Maybe that emits `Some.value` of those items emitted by the source SingleSource that are `Some`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Single<out Optional<T>>.filterSome(): Maybe<T> = ofType<Some<T>>().map { it.value }

/**
* Filters items emitted by an ObservableSource by only emitting those that are `None`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Observable that emits `Unit` for each item emitted by the source ObservableSource that is `None`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Observable<out Optional<T>>.filterNone(): Observable<Unit> = ofType<None>().map { Unit }

/**
* Filters items emitted by an Publisher by only emitting those that are `None`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Flowable that emits `Unit` for each item emitted by the source Publisher that is `None`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Flowable<out Optional<T>>.filterNone(): Flowable<Unit> = ofType<None>().map { Unit }

/**
* Filters items emitted by an MaybeSource by only emitting those that are `None`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Maybe that emits `Unit` for each item emitted by the source MaybeSource that is `None`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Maybe<out Optional<T>>.filterNone(): Maybe<Unit> = ofType<None>().map { Unit }

/**
* Filters items emitted by an SingleSource by only emitting those that are `None`.
* <p>
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png" alt="">
* <dl>
* <dt><b>Scheduler:</b></dt>
* <dd>{@code filter} does not operate by default on a particular {@link Scheduler}.</dd>
* </dl>
*
* @return an Maybe that emits `Unit` for each item emitted by the source SingleSource that is `None`.
* @see <a href="http://reactivex.io/documentation/operators/filter.html">ReactiveX operators documentation: Filter</a>
*/
fun <T : Any> Single<out Optional<T>>.filterNone(): Maybe<Unit> = ofType<None>().map { Unit }
Loading

0 comments on commit 868bab7

Please sign in to comment.