-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement
last
and lastOption
operators
The `lastOption` operator returns the last element in `Source` wrapped in `Some` or `None` in case when source is empty. Note that this is a terminal operation for source e.g.: Source.empty[Int].lastOption() // None val s = Source.fromValues(1, 2) s.lastOption() // Some(2) s.receive() // ChannelClosed.Done The `last` operator returns the last element in `Source` or throws `NoSuchElementException` in case when it is empty. In case when `receive()` fails then `ChannelClosedException.Error` exception is thrown. It is also a terminal operation e.g.: Source.empty[Int].last() // throws NoSuchElementException("cannot obtain last element from an empty source") val s = Source.fromValues(1, 2) s.last() // 2 s.receive() // ChannelClosed.Done Note that ChannelClosedException.Error was improved to contain `cause` exception (if available).
- Loading branch information
1 parent
931591f
commit 4f1d858
Showing
4 changed files
with
135 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
core/src/test/scala/ox/channels/SourceOpsLastOptionTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package ox.channels | ||
|
||
import org.scalatest.OptionValues | ||
import org.scalatest.flatspec.AnyFlatSpec | ||
import org.scalatest.matchers.should.Matchers | ||
import ox.* | ||
|
||
class SourceOpsLastOptionTest extends AnyFlatSpec with Matchers with OptionValues { | ||
behavior of "SourceOps.lastOption" | ||
|
||
it should "return None for the empty source" in supervised { | ||
Source.empty[Int].lastOption() shouldBe None | ||
} | ||
|
||
it should "throw ChannelClosedException.Error with exception and message that was thrown during retrieval" in supervised { | ||
the[ChannelClosedException.Error] thrownBy { | ||
Source | ||
.failed(new RuntimeException("source is broken")) | ||
.lastOption() | ||
} should have message "java.lang.RuntimeException: source is broken" | ||
} | ||
|
||
it should "throw ChannelClosedException.Error for source failed without exception" in supervised { | ||
the[ChannelClosedException.Error] thrownBy { | ||
Source.failedWithoutReason[Int]().lastOption() | ||
} | ||
} | ||
|
||
it should "return last element wrapped in Some for the non-empty source" in supervised { | ||
Source.fromValues(1, 2).lastOption().value shouldBe 2 | ||
} | ||
|
||
it should "drain the source" in supervised { | ||
val s = Source.fromValues(1) | ||
s.lastOption().value shouldBe 1 | ||
s.receive() shouldBe ChannelClosed.Done | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ox.channels | ||
|
||
import org.scalatest.flatspec.AnyFlatSpec | ||
import org.scalatest.matchers.should.Matchers | ||
import ox.* | ||
|
||
class SourceOpsLastTest extends AnyFlatSpec with Matchers { | ||
behavior of "SourceOps.last" | ||
|
||
it should "throw NoSuchElementException for the empty source" in supervised { | ||
the[NoSuchElementException] thrownBy { | ||
Source.empty[Int].last() | ||
} should have message "cannot obtain last element from an empty source" | ||
} | ||
|
||
it should "throw ChannelClosedException.Error with exception and message that was thrown during retrieval" in supervised { | ||
the[ChannelClosedException.Error] thrownBy { | ||
Source | ||
.failed(new RuntimeException("source is broken")) | ||
.last() | ||
} should have message "java.lang.RuntimeException: source is broken" | ||
} | ||
|
||
it should "throw ChannelClosedException.Error for source failed without exception" in supervised { | ||
the[ChannelClosedException.Error] thrownBy { | ||
Source.failedWithoutReason[Int]().last() | ||
} | ||
} | ||
|
||
it should "return last element for the non-empty source" in supervised { | ||
Source.fromValues(1, 2).last() shouldBe 2 | ||
} | ||
|
||
it should "drain the source" in supervised { | ||
val s = Source.fromValues(1) | ||
s.last() shouldBe 1 | ||
s.receive() shouldBe ChannelClosed.Done | ||
} | ||
} |