Skip to content

Commit 2375576

Browse files
refactor: Add more methods on Option (and, or, okOr, filter)
1 parent 23ea424 commit 2375576

2 files changed

Lines changed: 132 additions & 1 deletion

File tree

src/main/java/net/marcellperger/mathexpr/util/rs/Option.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,42 @@ default T expect(String msg) {
134134
default T unwrap() {
135135
return expect("Option.unwrap() got None value");
136136
}
137+
138+
default <E> Result<T, E> okOr(E err) {
139+
return ifThenElse(Result::newOk, () -> Result.newErr(err));
140+
}
141+
default <E> Result<T, E> okOrElse(Supplier<? extends E> errSupplier) {
142+
return ifThenElse(Result::newOk, () -> Result.newErr(errSupplier.get()));
143+
}
144+
145+
default <U> Option<U> and(Option<U> right) {
146+
return andThen((_v) -> right);
147+
}
148+
default <U> Option<U> andThen(Function<? super T, ? extends Option<U>> fn) {
149+
return switch (this) {
150+
case Some(T value) -> fn.apply(value);
151+
case None<T> n -> n.cast();
152+
};
153+
}
154+
155+
default Option<T> or(Option<T> right) {
156+
return orElse(() -> right);
157+
}
158+
default Option<T> orElse(Supplier<? extends Option<T>> orFn) {
159+
return switch (this) {
160+
case Some<T> s -> s;
161+
case None() -> orFn.get();
162+
};
163+
}
164+
165+
default Option<T> filter(Predicate<? super T> predicate) {
166+
return switch (this) {
167+
case Some(T value) -> predicate.test(value) ? this : newNone();
168+
case None<T> n -> n;
169+
};
170+
}
171+
137172
// no insert / get_or_insert(_*) / take(_if) / replace
138173
// (as record is immutable in Java)
139-
// TODO unwrap, check Rust docs
174+
// TODO check Rust docs
140175
}

src/test/java/net/marcellperger/mathexpr/util/rs/OptionTest.java

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,100 @@ void unwrap() {
225225
assertEquals("Option.unwrap() got None value", exc.getMessage());
226226
assertNull(exc.getCause(), "Expected no cause for Option.unwrap()");
227227
}
228+
229+
@Test
230+
void okOr() {
231+
assertEquals(Result.newOk(314), getSome().okOr("ERR_ARG"));
232+
assertEquals(Result.newErr("ERR_ARG"), getNone().okOr("ERR_ARG"));
233+
}
234+
235+
@Test
236+
void okOrElse() {
237+
MockedSupplier<String> ms = new MockedSupplier<>("ERR_FN_RETURN");
238+
{
239+
assertEquals(Result.newOk(314), getSome().okOrElse(ms));
240+
ms.assertNotCalled();
241+
}
242+
ms.reset();
243+
{
244+
assertEquals(Result.newErr("ERR_FN_RETURN"), getNone().okOrElse(ms));
245+
ms.assertCalledOnce();
246+
}
247+
}
248+
249+
@Test
250+
void and() {
251+
assertEquals(Option.newSome(91L), getSome().and(Option.newSome(91L)));
252+
assertEquals(Option.newNone(), getSome().and(Option.newNone()));
253+
assertEquals(Option.newNone(), getNone().and(Option.newSome(91L)));
254+
assertEquals(Option.newNone(), getNone().and(getNone()));
255+
}
256+
257+
@Test
258+
void andThen() {
259+
MockedFunction<Integer, Option<Long>> mfOk = new MockedFunction<>(Option.newSome(91L));
260+
MockedFunction<Integer, Option<Long>> mfErr = new MockedFunction<>(Option.newNone());
261+
{
262+
assertEquals(Option.newSome(91L), getSome().andThen(mfOk));
263+
mfOk.assertCalledOnceWith(314);
264+
assertEquals(Option.newNone(), getSome().andThen(mfErr));
265+
mfErr.assertCalledOnceWith(314);
266+
}
267+
mfOk.reset();
268+
mfErr.reset();
269+
{
270+
assertEquals(Option.newNone(), getNone().andThen(mfOk));
271+
mfOk.assertNotCalled();
272+
assertEquals(Option.newNone(), getNone().andThen(mfErr));
273+
mfErr.assertNotCalled();
274+
}
275+
}
276+
277+
@Test
278+
void filter() {
279+
MockedPredicate<Integer> mTrue = new MockedPredicate<>(true);
280+
MockedPredicate<Integer> mFalse = new MockedPredicate<>(false);
281+
{
282+
assertEquals(getSome(), getSome().filter(mTrue));
283+
mTrue.assertCalledOnceWith(314);
284+
assertEquals(getNone(), getSome().filter(mFalse));
285+
mFalse.assertCalledOnceWith(314);
286+
}
287+
mTrue.reset();
288+
mFalse.reset();
289+
{
290+
assertEquals(getNone(), getNone().filter(mTrue));
291+
mTrue.assertNotCalled();
292+
assertEquals(getNone(), getNone().filter(mFalse));
293+
mFalse.assertNotCalled();
294+
}
295+
}
296+
297+
@Test
298+
void or() {
299+
assertEquals(getSome(), getSome().or(Option.newSome(271)));
300+
assertEquals(getSome(), getSome().or(getNone()));
301+
assertEquals(Option.newSome(271), getNone().or(Option.newSome(271)));
302+
assertEquals(getNone(), getNone().or(getNone()));
303+
}
304+
305+
@Test
306+
void orElse() {
307+
MockedSupplier<Option<Integer>> mSome = new MockedSupplier<>(Option.newSome(271));
308+
MockedSupplier<Option<Integer>> mNone = new MockedSupplier<>(Option.newNone());
309+
{
310+
assertEquals(getSome(), getSome().orElse(mSome));
311+
mSome.assertNotCalled();
312+
assertEquals(getSome(), getSome().orElse(mNone));
313+
mNone.assertNotCalled();
314+
}
315+
mSome.reset();
316+
mNone.reset();
317+
{
318+
assertEquals(Option.newSome(271), getNone().orElse(mSome));
319+
mSome.assertCalledOnce();
320+
assertEquals(Option.newNone(), getNone().orElse(mNone));
321+
mNone.assertCalledOnce();
322+
}
323+
}
228324
}

0 commit comments

Comments
 (0)