From 4ba330b137df6147c0a1806943438b1cf4cc192a Mon Sep 17 00:00:00 2001 From: Leo40Git <7997354+Leo40Git@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:51:12 +0200 Subject: [PATCH 1/3] GsonReader: Rethrow exceptions as Gson types Closes QuiltMC#1. --- .../quiltmc/parsers/json/gson/GsonReader.java | 123 +++++++++++++++--- 1 file changed, 108 insertions(+), 15 deletions(-) diff --git a/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java b/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java index 95f6c74..94f726c 100644 --- a/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java +++ b/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java @@ -16,8 +16,13 @@ package org.quiltmc.parsers.json.gson; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; +import org.quiltmc.parsers.json.FormatViolationException; +import org.quiltmc.parsers.json.MalformedSyntaxException; +import org.quiltmc.parsers.json.ParseException; import java.io.IOException; import java.io.Reader; @@ -27,6 +32,7 @@ */ public class GsonReader extends JsonReader { private final org.quiltmc.parsers.json.JsonReader delegate; + /** * Creates a new instance that reads a JSON-encoded stream from {@code in}. * @@ -42,32 +48,71 @@ public org.quiltmc.parsers.json.JsonReader getDelegate() { @Override public void beginArray() throws IOException { - delegate.beginArray(); + try { + delegate.beginArray(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public void endArray() throws IOException { - delegate.endArray(); + try { + delegate.endArray(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public void beginObject() throws IOException { - delegate.beginObject(); + try { + delegate.beginObject(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public void endObject() throws IOException { - delegate.endObject(); + try { + delegate.endObject(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public boolean hasNext() throws IOException { - return delegate.hasNext(); + try { + return delegate.hasNext(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public JsonToken peek() throws IOException { - switch (delegate.peek()) { + org.quiltmc.parsers.json.JsonToken quiltToken; + try { + quiltToken = delegate.peek(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } + + switch (quiltToken) { case BEGIN_ARRAY: return JsonToken.BEGIN_ARRAY; case END_ARRAY: @@ -89,43 +134,85 @@ public JsonToken peek() throws IOException { case END_DOCUMENT: return JsonToken.END_DOCUMENT; default: - throw new IllegalArgumentException(); + throw new IllegalStateException("Delegate returned unrecognized token " + quiltToken); } } @Override public String nextName() throws IOException { - return delegate.nextName(); + try { + return delegate.nextName(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public String nextString() throws IOException { - return delegate.nextString(); + try { + return delegate.nextString(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public boolean nextBoolean() throws IOException { - return delegate.nextBoolean(); + try { + return delegate.nextBoolean(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public void nextNull() throws IOException { - delegate.nextNull(); + try { + delegate.nextNull(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public double nextDouble() throws IOException { - return delegate.nextDouble(); + try { + return delegate.nextDouble(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public long nextLong() throws IOException { - return delegate.nextLong(); + try { + return delegate.nextLong(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override public int nextInt() throws IOException { - return delegate.nextInt(); + try { + return delegate.nextInt(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override @@ -136,7 +223,13 @@ public void close() throws IOException { @Override public void skipValue() throws IOException { - delegate.skipValue(); + try { + delegate.skipValue(); + } catch (MalformedSyntaxException | FormatViolationException e) { + throw new JsonSyntaxException(e.getMessage(), e.getCause()); + } catch (ParseException e) { + throw new JsonParseException(e.getMessage(), e.getCause()); + } } @Override From 353237d73993c87d24f9267cdced8d6338b7a6d8 Mon Sep 17 00:00:00 2001 From: Leo40Git <7997354+Leo40Git@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:35:50 +0200 Subject: [PATCH 2/3] Extract exception wrapping code Don't throw away the original exceptions entirely (they're now used as the cause of the wrapping exceptions) me: "I should follow ix0rai's advice and extract the exception wrapping code" also me: makes 5 separate helper functions for various return types --- .../quiltmc/parsers/json/gson/GsonReader.java | 187 ++++++++++-------- 1 file changed, 100 insertions(+), 87 deletions(-) diff --git a/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java b/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java index 94f726c..be52539 100644 --- a/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java +++ b/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java @@ -46,71 +46,132 @@ public org.quiltmc.parsers.json.JsonReader getDelegate() { return delegate; } - @Override - public void beginArray() throws IOException { + @FunctionalInterface + private interface DelegateAction { + void call() throws IOException; + } + + @FunctionalInterface + private interface DelegateFunction { + T call() throws IOException; + } + + // these next interfaces are not strictly necessary, but they avoid boxing + // (if Java let primitives be generic parameters like C#, these wouldn't be needed. + // Project Panama when) + + @FunctionalInterface + private interface DelegateBooleanFunction { + boolean call() throws IOException; + } + + @FunctionalInterface + private interface DelegateIntFunction { + int call() throws IOException; + } + + @FunctionalInterface + private interface DelegateLongFunction { + long call() throws IOException; + } + + @FunctionalInterface + private interface DelegateDoubleFunction { + double call() throws IOException; + } + + private void rethrowGsonExceptions(DelegateAction action) throws IOException { try { - delegate.beginArray(); + action.call(); } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); + throw new JsonSyntaxException(e.getMessage(), e); } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); + throw new JsonParseException(e.getMessage(), e); } } - @Override - public void endArray() throws IOException { + private T rethrowGsonExceptions(DelegateFunction func) throws IOException { try { - delegate.endArray(); + return func.call(); } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); + throw new JsonSyntaxException(e.getMessage(), e); } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); + throw new JsonParseException(e.getMessage(), e); } } - @Override - public void beginObject() throws IOException { + private boolean rethrowGsonExceptions(DelegateBooleanFunction func) throws IOException + { try { - delegate.beginObject(); + return func.call(); } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); + throw new JsonSyntaxException(e.getMessage(), e); } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); + throw new JsonParseException(e.getMessage(), e); } } - @Override - public void endObject() throws IOException { + private int rethrowGsonExceptions(DelegateIntFunction func) throws IOException + { try { - delegate.endObject(); + return func.call(); } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); + throw new JsonSyntaxException(e.getMessage(), e); } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); + throw new JsonParseException(e.getMessage(), e); } } - @Override - public boolean hasNext() throws IOException { + private long rethrowGsonExceptions(DelegateLongFunction func) throws IOException + { try { - return delegate.hasNext(); + return func.call(); } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); + throw new JsonSyntaxException(e.getMessage(), e); } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); + throw new JsonParseException(e.getMessage(), e); } } - @Override - public JsonToken peek() throws IOException { - org.quiltmc.parsers.json.JsonToken quiltToken; + private double rethrowGsonExceptions(DelegateDoubleFunction func) throws IOException + { try { - quiltToken = delegate.peek(); + return func.call(); } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); + throw new JsonSyntaxException(e.getMessage(), e); } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); + throw new JsonParseException(e.getMessage(), e); } + } + + @Override + public void beginArray() throws IOException { + rethrowGsonExceptions(delegate::beginArray); + } + + @Override + public void endArray() throws IOException { + rethrowGsonExceptions(delegate::endArray); + } + + @Override + public void beginObject() throws IOException { + rethrowGsonExceptions(delegate::beginObject); + } + + @Override + public void endObject() throws IOException { + rethrowGsonExceptions(delegate::endObject); + } + + @Override + public boolean hasNext() throws IOException { + return rethrowGsonExceptions(delegate::hasNext); + } + + @Override + public JsonToken peek() throws IOException { + var quiltToken = rethrowGsonExceptions(delegate::peek); switch (quiltToken) { case BEGIN_ARRAY: @@ -140,79 +201,37 @@ public JsonToken peek() throws IOException { @Override public String nextName() throws IOException { - try { - return delegate.nextName(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + return rethrowGsonExceptions(delegate::nextName); } @Override public String nextString() throws IOException { - try { - return delegate.nextString(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + return rethrowGsonExceptions(delegate::nextString); } @Override public boolean nextBoolean() throws IOException { - try { - return delegate.nextBoolean(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + return rethrowGsonExceptions(delegate::nextBoolean); } @Override public void nextNull() throws IOException { - try { - delegate.nextNull(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + rethrowGsonExceptions(delegate::nextNull); } @Override public double nextDouble() throws IOException { - try { - return delegate.nextDouble(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + return rethrowGsonExceptions(delegate::nextDouble); } @Override public long nextLong() throws IOException { - try { - return delegate.nextLong(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + return rethrowGsonExceptions(delegate::nextLong); } @Override public int nextInt() throws IOException { - try { - return delegate.nextInt(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + return rethrowGsonExceptions(delegate::nextInt); } @Override @@ -223,13 +242,7 @@ public void close() throws IOException { @Override public void skipValue() throws IOException { - try { - delegate.skipValue(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e.getCause()); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e.getCause()); - } + rethrowGsonExceptions(delegate::skipValue); } @Override From 8c36931d2c2215da1365d3787facd4cf2b6c608e Mon Sep 17 00:00:00 2001 From: Leo40Git <7997354+Leo40Git@users.noreply.github.com> Date: Sun, 4 Feb 2024 19:37:14 +0200 Subject: [PATCH 3/3] Deduplication! --- .../quiltmc/parsers/json/gson/GsonReader.java | 99 +++---------------- 1 file changed, 16 insertions(+), 83 deletions(-) diff --git a/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java b/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java index be52539..8b502c0 100644 --- a/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java +++ b/gson/src/main/java/org/quiltmc/parsers/json/gson/GsonReader.java @@ -46,47 +46,20 @@ public org.quiltmc.parsers.json.JsonReader getDelegate() { return delegate; } - @FunctionalInterface - private interface DelegateAction { - void call() throws IOException; - } - @FunctionalInterface private interface DelegateFunction { T call() throws IOException; } - // these next interfaces are not strictly necessary, but they avoid boxing - // (if Java let primitives be generic parameters like C#, these wouldn't be needed. - // Project Panama when) - - @FunctionalInterface - private interface DelegateBooleanFunction { - boolean call() throws IOException; - } - @FunctionalInterface - private interface DelegateIntFunction { - int call() throws IOException; - } - - @FunctionalInterface - private interface DelegateLongFunction { - long call() throws IOException; - } - - @FunctionalInterface - private interface DelegateDoubleFunction { - double call() throws IOException; - } - - private void rethrowGsonExceptions(DelegateAction action) throws IOException { - try { - action.call(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e); + private interface DelegateAction extends DelegateFunction { + void run() throws IOException; + + @Override + default Void call() throws IOException + { + run(); + return null; } } @@ -100,68 +73,28 @@ private T rethrowGsonExceptions(DelegateFunction func) throws IOException } } - private boolean rethrowGsonExceptions(DelegateBooleanFunction func) throws IOException - { - try { - return func.call(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e); - } - } - - private int rethrowGsonExceptions(DelegateIntFunction func) throws IOException - { - try { - return func.call(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e); - } - } - - private long rethrowGsonExceptions(DelegateLongFunction func) throws IOException - { - try { - return func.call(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e); - } - } - - private double rethrowGsonExceptions(DelegateDoubleFunction func) throws IOException - { - try { - return func.call(); - } catch (MalformedSyntaxException | FormatViolationException e) { - throw new JsonSyntaxException(e.getMessage(), e); - } catch (ParseException e) { - throw new JsonParseException(e.getMessage(), e); - } + private void rethrowGsonExceptionsVoid(DelegateAction action) throws IOException { + rethrowGsonExceptions(action); } @Override public void beginArray() throws IOException { - rethrowGsonExceptions(delegate::beginArray); + rethrowGsonExceptionsVoid(delegate::beginArray); } @Override public void endArray() throws IOException { - rethrowGsonExceptions(delegate::endArray); + rethrowGsonExceptionsVoid(delegate::endArray); } @Override public void beginObject() throws IOException { - rethrowGsonExceptions(delegate::beginObject); + rethrowGsonExceptionsVoid(delegate::beginObject); } @Override public void endObject() throws IOException { - rethrowGsonExceptions(delegate::endObject); + rethrowGsonExceptionsVoid(delegate::endObject); } @Override @@ -216,7 +149,7 @@ public boolean nextBoolean() throws IOException { @Override public void nextNull() throws IOException { - rethrowGsonExceptions(delegate::nextNull); + rethrowGsonExceptionsVoid(delegate::nextNull); } @Override @@ -242,7 +175,7 @@ public void close() throws IOException { @Override public void skipValue() throws IOException { - rethrowGsonExceptions(delegate::skipValue); + rethrowGsonExceptionsVoid(delegate::skipValue); } @Override