From 133e1d75f9fa7810ecf164cc1096209155101c53 Mon Sep 17 00:00:00 2001 From: JFronny Date: Tue, 30 Apr 2024 15:53:01 +0200 Subject: [PATCH] feat(serialize-databind): implement alternate API for parsing via ADTs. Probably still need to figure out how to ensure unchecked exceptions are not propagated --- .../jfronny/commons/serialize/RToken.java | 12 +++ .../commons/serialize/SerializeReader.java | 84 ++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/RToken.java diff --git a/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/RToken.java b/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/RToken.java new file mode 100644 index 0000000..f8c4e04 --- /dev/null +++ b/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/RToken.java @@ -0,0 +1,12 @@ +package io.gitlab.jfronny.commons.serialize; + +public sealed interface RToken { + enum Simple implements RToken { + BEGIN_ARRAY, END_ARRAY, BEGIN_OBJECT, END_OBJECT, NULL, END_DOCUMENT + } + + record Name(java.lang.String name) implements RToken {} + record String(java.lang.String value) implements RToken {} + record Number(java.lang.Number value) implements RToken {} + record Boolean(boolean value) implements RToken {} +} diff --git a/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/SerializeReader.java b/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/SerializeReader.java index a997921..2b58f95 100644 --- a/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/SerializeReader.java +++ b/commons-serialize/src/main/java/io/gitlab/jfronny/commons/serialize/SerializeReader.java @@ -1,8 +1,23 @@ package io.gitlab.jfronny.commons.serialize; import io.gitlab.jfronny.commons.SamWithReceiver; +import io.gitlab.jfronny.commons.throwable.ExceptionWrapper; +import org.jetbrains.annotations.NotNull; -public abstract class SerializeReader> implements AutoCloseable { +import java.util.Iterator; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * A reader for serialized data. + * Although it is marked as {@link Iterable}, you should make sure iteration is only done once, since it consumes tokens! + * + * @param the exception type + * @param the reader type + */ +public abstract class SerializeReader> implements AutoCloseable, Iterable { protected boolean lenient = false; protected boolean serializeSpecialFloatingPointValues = false; @@ -67,6 +82,69 @@ public abstract class SerializeReader RToken.Simple.BEGIN_ARRAY; + case END_ARRAY -> RToken.Simple.END_ARRAY; + case BEGIN_OBJECT -> RToken.Simple.BEGIN_OBJECT; + case END_OBJECT -> RToken.Simple.END_OBJECT; + case NAME -> new RToken.Name(nextName()); + case STRING -> new RToken.String(nextString()); + case NUMBER -> new RToken.Number(nextNumber()); + case BOOLEAN -> new RToken.Boolean(nextBoolean()); + case NULL -> { + nextNull(); + yield RToken.Simple.NULL; + } + case END_DOCUMENT -> RToken.Simple.END_DOCUMENT; + }; + } + + /** + * 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}. + * @return a stream of the tokens + */ + public @NotNull Stream stream() { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator(), Spliterator.NONNULL | Spliterator.ORDERED), false); + } + + /** + * 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}. + * @return an iterator over the tokens + */ + @Override + public @NotNull Iterator iterator() { + return new Iterator<>() { + @Override + public boolean hasNext() { + try { + return SerializeReader.this.hasNext(); + } catch (Exception e) { + throw ExceptionWrapper.wrap(e); + } + } + + @Override + public RToken next() { + try { + return SerializeReader.this.next(); + } catch (Exception e) { + throw ExceptionWrapper.wrap(e); + } + } + }; + } + /** * Copies the current element to the writer. * @@ -113,6 +191,10 @@ public abstract class SerializeReader