/*
* Copyright (c) 2024-2025, Antonio Gabriel Muñoz Conejo <me at tonivade dot es>
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.vavr.effect;
import org.jspecify.annotations.Nullable;
import io.vavr.PartialFunction;
import io.vavr.control.Option;
final class CallStack<T> {
@Nullable
private StackItem<T> top = new StackItem<>();
void push() {
if (top != null) {
top.push();
}
}
void pop() {
if (top == null) {
return;
}
if (top.count() > 0) {
top.pop();
} else {
top = top.prev();
}
}
void add(PartialFunction<? super Throwable, ? extends IO<? extends T>> mapError) {
if (top == null) {
return;
}
if (top.count() > 0) {
top.pop();
top = new StackItem<>(top);
}
top.add(mapError);
}
Option<IO<T>> tryHandle(Throwable error) {
while (top != null) {
top.reset();
Option<IO<T>> result = top.tryHandle(error);
if (result.isDefined()) {
return result;
} else {
top = top.prev();
}
}
return Option.none();
}
// XXX: https://www.baeldung.com/java-sneaky-throws
@SuppressWarnings("unchecked")
<X extends Throwable, R> R sneakyThrow(Throwable t) throws X {
throw (X) t;
}
}