fix(serialize): throw checked exceptions in SerializeReader iterator. Probably better than just trusting every TypeAdapter to catch wrapping exceptions.
ci/woodpecker/push/woodpecker Pipeline failed
Details
ci/woodpecker/push/woodpecker Pipeline failed
Details
This commit is contained in:
parent
21beed944d
commit
754f418ceb
|
@ -1,10 +1,11 @@
|
|||
package io.gitlab.jfronny.commons.serialize;
|
||||
|
||||
import io.gitlab.jfronny.commons.SamWithReceiver;
|
||||
import io.gitlab.jfronny.commons.throwable.ExceptionWrapper;
|
||||
import io.gitlab.jfronny.commons.throwable.Unchecked;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -109,8 +110,8 @@ public abstract class SerializeReader<TEx extends Exception, T extends Serialize
|
|||
/**
|
||||
* Returns a {@link Stream} of the tokens within the current object or array.
|
||||
* The stream consumes tokens and advances the reader, so it is not possible to iterate over the tokens more than once.
|
||||
* Additionally, iteration may throw {@link RuntimeException}s created with {@link ExceptionWrapper#wrap(Throwable)} around {@link TEx}.
|
||||
* That exception MUST be caught and handled by the caller immediately. Throwing it in a TypeAdapter is NOT allowed.
|
||||
* Additionally, although it is not marked as such, iteration may throw a TEx.
|
||||
* The caller is responsible for making sure it is caught and not propagated.
|
||||
*
|
||||
* @return a stream of the tokens
|
||||
*/
|
||||
|
@ -121,32 +122,59 @@ public abstract class SerializeReader<TEx extends Exception, T extends Serialize
|
|||
/**
|
||||
* Returns an {@link Iterator} over the tokens within the current object or array.
|
||||
* The iterator consumes tokens and advances the reader, so it is not possible to iterate over the tokens more than once.
|
||||
* Additionally, iteration may throw {@link RuntimeException}s created with {@link ExceptionWrapper#wrap(Throwable)} around {@link TEx}.
|
||||
* That exception MUST be caught and handled by the caller immediately. Throwing it in a TypeAdapter is NOT allowed.
|
||||
* Additionally, although it is not marked as such, iteration may throw a TEx.
|
||||
* The caller is responsible for making sure it is caught and not propagated.
|
||||
*
|
||||
* @return an iterator over the tokens
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Iterator<RToken> iterator() {
|
||||
return new Iterator<>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
try {
|
||||
return SerializeReader.this.hasNext();
|
||||
} catch (Exception e) {
|
||||
throw ExceptionWrapper.wrap(e);
|
||||
}
|
||||
}
|
||||
public @NotNull TokenIterator iterator() {
|
||||
return new TokenIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RToken next() {
|
||||
try {
|
||||
return SerializeReader.this.next();
|
||||
} catch (Exception e) {
|
||||
throw ExceptionWrapper.wrap(e);
|
||||
}
|
||||
/**
|
||||
* An iterator over the tokens within the current object or array.
|
||||
* The iterator consumes tokens and advances the reader, so it is not possible to iterate over the tokens more than once.
|
||||
* Additionally, although it is not marked as such in code, iteration may throw a TEx.
|
||||
* <p>
|
||||
* Note: this iterator tracks the depth of the tree it traversed,
|
||||
* so consuming BEGIN_OBJECT or BEGIN_ARRAY tokens while it is in use
|
||||
* without consuming the corresponding END_OBJECT or END_ARRAY tokens before the next call to it is not supported.
|
||||
*/
|
||||
public class TokenIterator implements Iterator<RToken> {
|
||||
int depth = 0;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws TEx if an error occurs
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
try {
|
||||
return depth > 0 || SerializeReader.this.hasNext();
|
||||
} catch (Exception e) {
|
||||
return Unchecked.sneakyThrow(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws TEx if an error occurs
|
||||
*/
|
||||
@Override
|
||||
public RToken next() {
|
||||
if (!hasNext()) throw new NoSuchElementException("No more tokens");
|
||||
try {
|
||||
RToken token = SerializeReader.this.next();
|
||||
if (token == RToken.Simple.BEGIN_ARRAY || token == RToken.Simple.BEGIN_OBJECT) {
|
||||
depth++;
|
||||
} else if (token == RToken.Simple.END_ARRAY || token == RToken.Simple.END_OBJECT) {
|
||||
depth--;
|
||||
}
|
||||
return token;
|
||||
} catch (Exception e) {
|
||||
return Unchecked.sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.gitlab.jfronny.commons.concurrent;
|
||||
|
||||
import io.gitlab.jfronny.commons.throwable.Assume;
|
||||
import io.gitlab.jfronny.commons.throwable.Unchecked;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public interface WithScopedValue<T> {
|
||||
|
@ -8,12 +9,12 @@ public interface WithScopedValue<T> {
|
|||
@ApiStatus.Internal T self();
|
||||
|
||||
default <TEx1 extends Throwable, TEx2 extends Throwable> void withContext(Action<TEx1, TEx2> action) throws TEx1, TEx2 {
|
||||
Assume.<TEx1>reintroduce();
|
||||
Assume.<TEx2>reintroduce(() -> ScopedValue.runWhere(getAttached(), self(), Assume.isSafe(action::run)));
|
||||
Unchecked.<TEx1>reintroduce();
|
||||
Unchecked.<TEx2>reintroduce(() -> ScopedValue.runWhere(getAttached(), self(), Assume.isSafe(action::run)));
|
||||
}
|
||||
default <T, TEx1 extends Throwable, TEx2 extends Throwable> T withContext(Returnable<T, TEx1, TEx2> action) throws TEx1, TEx2 {
|
||||
Assume.<TEx1>reintroduce();
|
||||
return Assume.<T, TEx2>reintroduce(() -> ScopedValue.getWhere(getAttached(), self(), Assume.isSafe(action::run)));
|
||||
Unchecked.<TEx1>reintroduce();
|
||||
return Unchecked.<T, TEx2>reintroduce(() -> ScopedValue.getWhere(getAttached(), self(), Assume.isSafe(action::run)));
|
||||
}
|
||||
|
||||
interface Returnable<T, TEx1 extends Throwable, TEx2 extends Throwable> {
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.function.Supplier;
|
|||
|
||||
/**
|
||||
* A utility class to hide checked exceptions from the java compiler.
|
||||
* For immediate execution or to reintroduce exceptions, use {@link Unchecked}.
|
||||
*/
|
||||
public class Assume {
|
||||
/**
|
||||
|
@ -33,63 +34,28 @@ public class Assume {
|
|||
return rn::get;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides an exception from the java compiler, effectively making it unchecked.
|
||||
* Runs a runnable.
|
||||
*
|
||||
* @param runnable the runnable to run
|
||||
* @param <TEx> the exception the runnable might throw
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static <TEx extends Throwable> void sneaky(ThrowingRunnable<TEx> runnable) {
|
||||
isSafe(runnable).run();
|
||||
Unchecked.sneaky(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides an exception from the java compiler, effectively making it unchecked.
|
||||
* Runs a supplier and returns the result.
|
||||
*
|
||||
* @param supplier the supplier to run
|
||||
* @param <T> the return type of the supplier
|
||||
* @param <TEx> the exception the supplier might throw
|
||||
* @return the result of the supplier
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static <T, TEx extends Throwable> T sneaky(ThrowingSupplier<T, TEx> supplier) {
|
||||
return isSafe(supplier).get();
|
||||
return Unchecked.sneaky(supplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reintroduces an exception previously made sneaky, allowing you to catch it.
|
||||
* The call does nothing except tricking the compiler into thinking that the exception is thrown.
|
||||
*
|
||||
* @param <TEx> the exception to reintroduce into the set of possible exceptions
|
||||
* @throws TEx the introduced exception
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static <TEx extends Throwable> void reintroduce() throws TEx {
|
||||
Unchecked.reintroduce();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reintroduces an exception previously made sneaky, allowing you to catch it.
|
||||
* Simply runs the runnable.
|
||||
*
|
||||
* @param runnable the runnable to run
|
||||
* @param <TEx> the exception to reintroduce into the set of possible exceptions
|
||||
* @throws TEx the exception that was thrown by the runnable
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static <TEx extends Throwable> void reintroduce(Runnable runnable) throws TEx {
|
||||
runnable.run();
|
||||
Unchecked.reintroduce(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reintroduces an exception previously made sneaky, allowing you to catch it.
|
||||
* Simply runs the supplier and returns the result.
|
||||
*
|
||||
* @param supplier the supplier to run
|
||||
* @param <T> the return type of the supplier
|
||||
* @param <TEx> the exception to reintroduce into the set of possible exceptions
|
||||
* @return the result of the supplier
|
||||
* @throws TEx the exception that was thrown by the supplier
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static <T, TEx extends Throwable> T reintroduce(Supplier<T> supplier) throws TEx {
|
||||
return supplier.get();
|
||||
return Unchecked.reintroduce(supplier);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package io.gitlab.jfronny.commons.throwable;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A utility class to hide checked exceptions from the java compiler.
|
||||
* For conversion of checked lambdas to unchecked lambdas, use {@link Assume}.
|
||||
*/
|
||||
public class Unchecked {
|
||||
/**
|
||||
* Throws a checked exception without the need to declare it.
|
||||
*
|
||||
* @param t the exception to throw
|
||||
*/
|
||||
public static <T> T sneakyThrow(Throwable t) {
|
||||
return sneaky(() -> {
|
||||
throw t;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides an exception from the java compiler, effectively making it unchecked.
|
||||
* Runs a runnable.
|
||||
*
|
||||
* @param runnable the runnable to run
|
||||
* @param <TEx> the exception the runnable might throw
|
||||
*/
|
||||
public static <TEx extends Throwable> void sneaky(ThrowingRunnable<TEx> runnable) {
|
||||
Assume.isSafe(runnable).run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides an exception from the java compiler, effectively making it unchecked.
|
||||
* Runs a supplier and returns the result.
|
||||
*
|
||||
* @param supplier the supplier to run
|
||||
* @param <T> the return type of the supplier
|
||||
* @param <TEx> the exception the supplier might throw
|
||||
* @return the result of the supplier
|
||||
*/
|
||||
public static <T, TEx extends Throwable> T sneaky(ThrowingSupplier<T, TEx> supplier) {
|
||||
return Assume.isSafe(supplier).get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reintroduces an exception previously made sneaky, allowing you to catch it.
|
||||
* The call does nothing except tricking the compiler into thinking that the exception is thrown.
|
||||
*
|
||||
* @param <TEx> the exception to reintroduce into the set of possible exceptions
|
||||
* @throws TEx the introduced exception
|
||||
*/
|
||||
public static <TEx extends Throwable> void reintroduce() throws TEx {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reintroduces an exception previously made sneaky, allowing you to catch it.
|
||||
* Simply runs the runnable.
|
||||
*
|
||||
* @param runnable the runnable to run
|
||||
* @param <TEx> the exception to reintroduce into the set of possible exceptions
|
||||
* @throws TEx the exception that was thrown by the runnable
|
||||
*/
|
||||
public static <TEx extends Throwable> void reintroduce(Runnable runnable) throws TEx {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reintroduces an exception previously made sneaky, allowing you to catch it.
|
||||
* Simply runs the supplier and returns the result.
|
||||
*
|
||||
* @param supplier the supplier to run
|
||||
* @param <T> the return type of the supplier
|
||||
* @param <TEx> the exception to reintroduce into the set of possible exceptions
|
||||
* @return the result of the supplier
|
||||
* @throws TEx the exception that was thrown by the supplier
|
||||
*/
|
||||
public static <T, TEx extends Throwable> T reintroduce(Supplier<T> supplier) throws TEx {
|
||||
return supplier.get();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue