diff --git a/common-testing/src/test/java/io/carbynestack/common/result/FailureTest.java b/common-testing/src/test/java/io/carbynestack/common/result/FailureTest.java index ff79019..8965410 100644 --- a/common-testing/src/test/java/io/carbynestack/common/result/FailureTest.java +++ b/common-testing/src/test/java/io/carbynestack/common/result/FailureTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.function.Predicate; @@ -70,6 +71,28 @@ void peekNullPointerException() { .isExactlyInstanceOf(NullPointerException.class); } + @Test + void tryPeek() { + AtomicInteger output = new AtomicInteger(-1); + result.tryPeek(output::set, reason * 2); + assertThat(output).hasValue(-1); + } + + @Test + void tryPeekWithException() { + Result res = result.tryPeek(v -> { + throw new IOException("-11"); + }, reason * 2); + assertThat(res).isFailure(); + assertThat(res).hasReason(reason); + } + + @Test + void tryPeekNullPointerException() { + assertThatThrownBy(() -> result.tryPeek(null, reason * 2)) + .isExactlyInstanceOf(NullPointerException.class); + } + @Test void recover() { assertThat(result.recover(r -> r * 2)).hasValue(42); diff --git a/common-testing/src/test/java/io/carbynestack/common/result/SuccessTest.java b/common-testing/src/test/java/io/carbynestack/common/result/SuccessTest.java index eca5726..ed2fc6f 100644 --- a/common-testing/src/test/java/io/carbynestack/common/result/SuccessTest.java +++ b/common-testing/src/test/java/io/carbynestack/common/result/SuccessTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import java.io.IOException; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -71,6 +72,29 @@ void peekNullPointerException() { .isExactlyInstanceOf(NullPointerException.class); } + @Test + void tryPeek() { + AtomicInteger output = new AtomicInteger(-1); + result.tryPeek(output::set, -11); + assertThat(output).hasValue(value); + } + + @Test + void tryPeekWithException() { + int reason = -11; + Result res = result.tryPeek(v -> { + throw new IOException("-11"); + }, reason); + assertThat(res).isFailure(); + assertThat(res).hasReason(reason); + } + + @Test + void tryPeekNullPointerException() { + assertThatThrownBy(() -> result.tryPeek(null, -11)) + .isExactlyInstanceOf(NullPointerException.class); + } + @Test void recover() { assertThat(result.recover(identity())).hasValue(value); diff --git a/common-types/src/main/java/io/carbynestack/common/result/Failure.java b/common-types/src/main/java/io/carbynestack/common/result/Failure.java index 63ac102..9b2534e 100644 --- a/common-types/src/main/java/io/carbynestack/common/result/Failure.java +++ b/common-types/src/main/java/io/carbynestack/common/result/Failure.java @@ -7,6 +7,7 @@ package io.carbynestack.common.result; import io.carbynestack.common.Generated; +import io.carbynestack.common.function.AnyThrowingConsumer; import java.util.Objects; import java.util.Optional; @@ -104,6 +105,24 @@ public Result peek(Consumer consumer) { return this; } + /** + * {@inheritDoc} + * + * @param consumer the consumer of {@link Success#value()} + * @param reason the failure reason in case of the consumer throwing + * a {@code Throwable} + * @return {@code this} + * @throws NullPointerException if the consumer is {@code null} + * @version JDK 8 + * @see #map(Function) + * @since 0.1.0 + */ + @Override + public Result tryPeek(AnyThrowingConsumer consumer, F reason) { + requireNonNull(consumer); + return this; + } + /** * {@inheritDoc} * diff --git a/common-types/src/main/java/io/carbynestack/common/result/Result.java b/common-types/src/main/java/io/carbynestack/common/result/Result.java index 188b7a2..9d5379b 100644 --- a/common-types/src/main/java/io/carbynestack/common/result/Result.java +++ b/common-types/src/main/java/io/carbynestack/common/result/Result.java @@ -7,6 +7,7 @@ package io.carbynestack.common.result; import io.carbynestack.common.CsFailureReason; +import io.carbynestack.common.function.AnyThrowingConsumer; import io.carbynestack.common.function.AnyThrowingSupplier; import io.carbynestack.common.function.ThrowingSupplier; @@ -123,6 +124,24 @@ default boolean isFailure() { */ Result peek(Consumer consumer); + /** + * If the {@code Result} is a {@link Success}, invokes the provided + * consumer with the {@link Success#value()}. Otherwise, the + * {@link Failure} is returned. + * + *

In case the consumer throws a {@link Throwable} the failure reason + * is returned as a {@code Failure}.
+ * + * @param consumer the consumer of {@link Success#value()} + * @param reason the failure reason in case of the consumer throwing + * a {@code Throwable} + * @return {@code this} + * @throws NullPointerException if the consumer is {@code null} + * @see #map(Function) + * @since 0.1.0 + */ + Result tryPeek(AnyThrowingConsumer consumer, F reason); + /** * If the {@code Result} is a {@link Failure}, returns the result of * applying the given mapping function to the {@link Failure#reason()}. diff --git a/common-types/src/main/java/io/carbynestack/common/result/Success.java b/common-types/src/main/java/io/carbynestack/common/result/Success.java index 8d88ee3..4959edd 100644 --- a/common-types/src/main/java/io/carbynestack/common/result/Success.java +++ b/common-types/src/main/java/io/carbynestack/common/result/Success.java @@ -7,6 +7,7 @@ package io.carbynestack.common.result; import io.carbynestack.common.Generated; +import io.carbynestack.common.function.AnyThrowingConsumer; import java.util.Objects; import java.util.Optional; @@ -105,6 +106,29 @@ public Result peek(Consumer consumer) { return this; } + /** + * {@inheritDoc} + * + * @param consumer the consumer of {@link Success#value()} + * @param reason the failure reason in case of the consumer throwing + * a {@code Throwable} + * @return {@code this} + * @throws NullPointerException if the consumer is {@code null} + * @version JDK 8 + * @see #map(Function) + * @since 0.1.0 + */ + @Override + public Result tryPeek(AnyThrowingConsumer consumer, F reason) { + requireNonNull(consumer); + try { + consumer.accept(this.value()); + return this; + } catch (Throwable throwable) { + return new Failure<>(reason); + } + } + /** * {@inheritDoc} * diff --git a/common-types/src/main/java17/io/carbynestack/common/result/Failure.java b/common-types/src/main/java17/io/carbynestack/common/result/Failure.java index 9d56dfe..c008ca7 100644 --- a/common-types/src/main/java17/io/carbynestack/common/result/Failure.java +++ b/common-types/src/main/java17/io/carbynestack/common/result/Failure.java @@ -6,6 +6,8 @@ */ package io.carbynestack.common.result; +import io.carbynestack.common.function.AnyThrowingConsumer; + import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; @@ -74,6 +76,24 @@ public Result peek(Consumer consumer) { return this; } + /** + * {@inheritDoc} + * + * @param consumer the consumer of {@link Success#value()} + * @param reason the failure reason in case of the consumer throwing + * a {@code Throwable} + * @return {@code this} + * @throws NullPointerException if the consumer is {@code null} + * @version JDK 17 + * @see #map(Function) + * @since 0.1.0 + */ + @Override + public Result tryPeek(AnyThrowingConsumer consumer, F reason) { + requireNonNull(consumer); + return this; + } + /** * {@inheritDoc} * diff --git a/common-types/src/main/java17/io/carbynestack/common/result/Result.java b/common-types/src/main/java17/io/carbynestack/common/result/Result.java index 42269aa..933c1b6 100644 --- a/common-types/src/main/java17/io/carbynestack/common/result/Result.java +++ b/common-types/src/main/java17/io/carbynestack/common/result/Result.java @@ -7,6 +7,7 @@ package io.carbynestack.common.result; import io.carbynestack.common.CsFailureReason; +import io.carbynestack.common.function.AnyThrowingConsumer; import io.carbynestack.common.function.AnyThrowingSupplier; import io.carbynestack.common.function.ThrowingSupplier; @@ -123,6 +124,24 @@ default boolean isFailure() { */ Result peek(Consumer consumer); + /** + * If the {@code Result} is a {@link Success}, invokes the provided + * consumer with the {@link Success#value()}. Otherwise, the + * {@link Failure} is returned. + * + *

In case the consumer throws a {@link Throwable} the failure reason + * is returned as a {@code Failure}.
+ * + * @param consumer the consumer of {@link Success#value()} + * @param reason the failure reason in case of the consumer throwing + * a {@code Throwable} + * @return {@code this} + * @throws NullPointerException if the consumer is {@code null} + * @see #map(Function) + * @since 0.1.0 + */ + Result tryPeek(AnyThrowingConsumer consumer, F reason); + /** * If the {@code Result} is a {@link Failure}, returns the result of * applying the given mapping function to the {@link Failure#reason()}. diff --git a/common-types/src/main/java17/io/carbynestack/common/result/Success.java b/common-types/src/main/java17/io/carbynestack/common/result/Success.java index 5c13f07..3b0c397 100644 --- a/common-types/src/main/java17/io/carbynestack/common/result/Success.java +++ b/common-types/src/main/java17/io/carbynestack/common/result/Success.java @@ -6,6 +6,8 @@ */ package io.carbynestack.common.result; +import io.carbynestack.common.function.AnyThrowingConsumer; + import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; @@ -75,6 +77,29 @@ public Result peek(Consumer consumer) { return this; } + /** + * {@inheritDoc} + * + * @param consumer the consumer of {@link Success#value()} + * @param reason the failure reason in case of the consumer throwing + * a {@code Throwable} + * @return {@code this} + * @throws NullPointerException if the consumer is {@code null} + * @version JDK 17 + * @see #map(Function) + * @since 0.1.0 + */ + @Override + public Result tryPeek(AnyThrowingConsumer consumer, F reason) { + requireNonNull(consumer); + try { + consumer.accept(this.value()); + return this; + } catch (Throwable throwable) { + return new Failure<>(reason); + } + } + /** * {@inheritDoc} * diff --git a/common-types/src/test/java/io/carbynestack/common/result/ResultTest.java b/common-types/src/test/java/io/carbynestack/common/result/ResultTest.java index bf0b353..39bca7c 100644 --- a/common-types/src/test/java/io/carbynestack/common/result/ResultTest.java +++ b/common-types/src/test/java/io/carbynestack/common/result/ResultTest.java @@ -75,6 +75,17 @@ void result() { assertThat(res.stream().toList()).isEmpty(); } + @Test + void tryPeek() { + assertThat(new Success<>(12) + .tryPeek(System.out::println, -1) + .tryPeek(v -> { + throw new IOException(); + }, -1) + .tryPeek(System.out::println, -1) + .isFailure()).isTrue(); + } + @Test void of() { assertThat(Result.of(() -> 12).isSuccess()).isTrue();