summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gson/src/test/java/moe/nea/jcp/gson/test/TestBasic.java58
-rw-r--r--src/main/java/moe/nea/pcj/json/DuringKeyExtraction.java4
-rw-r--r--src/main/java/moe/nea/pcj/json/InSubType.java4
-rw-r--r--src/main/java/moe/nea/pcj/json/MapCodec.java24
-rw-r--r--src/main/java/moe/nea/pcj/json/UnknownSubtype.java10
5 files changed, 79 insertions, 21 deletions
diff --git a/gson/src/test/java/moe/nea/jcp/gson/test/TestBasic.java b/gson/src/test/java/moe/nea/jcp/gson/test/TestBasic.java
index 628518c..6e70665 100644
--- a/gson/src/test/java/moe/nea/jcp/gson/test/TestBasic.java
+++ b/gson/src/test/java/moe/nea/jcp/gson/test/TestBasic.java
@@ -13,12 +13,15 @@ import moe.nea.pcj.Result;
import moe.nea.pcj.json.AtField;
import moe.nea.pcj.json.AtIndex;
import moe.nea.pcj.json.DuplicateJsonKey;
+import moe.nea.pcj.json.DuringKeyExtraction;
+import moe.nea.pcj.json.InSubType;
import moe.nea.pcj.json.JsonLikeError;
import moe.nea.pcj.json.JsonLikeOperations;
import moe.nea.pcj.json.MissingKey;
import moe.nea.pcj.json.NamedObject;
import moe.nea.pcj.json.RecordJoiners;
import moe.nea.pcj.json.UnexpectedJsonElement;
+import moe.nea.pcj.json.UnknownSubtype;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -37,7 +40,7 @@ public class TestBasic {
);
}
- private <T> void assertSuccess(Result<T, ?> result, T expected) {
+ private <T> void assertSuccess(Result<? extends T, ?> result, T expected) {
for (Object error : result.errors()) {
throw new AssertionError(error.toString());
}
@@ -146,6 +149,10 @@ public class TestBasic {
new AtIndex(0, new UnexpectedJsonElement("object", mkPrim("foo"))));
}
+ <T> T implicitCast(T t) {
+ return t;
+ }
+
@Test
void testDispatched() {
var testObjectCodec = RecordJoiners.join(
@@ -157,18 +164,43 @@ public class TestBasic {
codecs.STRING.fieldOf("test").withGetter(OtherTestObject::test),
OtherTestObject::new
);
- codecs.STRING.fieldOf("type")
- .<Parent>dispatch(
- obj -> switch (obj) {
- case OtherTestObject ignored -> "other";
- case TestObject ignored -> "normal";
- },
- key -> switch (key) {
- case "other" -> otherObjectCodec;
- case "normal" -> testObjectCodec;
- default -> throw new AssertionError("Unknown thing");
- }
- );
+ var parentCodec = codecs.STRING.fieldOf("type")
+ .<Parent>dispatch(
+ obj -> switch (obj) {
+ case OtherTestObject ignored -> "other";
+ case TestObject ignored -> "normal";
+ },
+ key -> switch (key) {
+ case "other" -> Result.ok(otherObjectCodec);
+ case "normal" -> Result.ok(testObjectCodec);
+ default -> Result.fail(new UnknownSubtype<>(key, "other", "normal"));
+ }
+ );
+ assertSuccess(decode(parentCodec.codec(), mkJsonObject(
+ "type", "other",
+ "test", "test"
+ )), new OtherTestObject("test"));
+ assertSuccess(decode(parentCodec.codec(), mkJsonObject(
+ "type", "normal",
+ "foo", "fooVal",
+ "bar", 10
+ )), new TestObject("fooVal", 10));
+ assertFail(
+ decode(parentCodec.codec(), mkJsonObject(
+ "type", "unknown",
+ "foo", "fooVal",
+ "bar", 10
+ )),
+ new DuringKeyExtraction(new UnknownSubtype<>("unknown", "other", "normal"))
+ );
+ assertFail(
+ decode(parentCodec.codec(), mkJsonObject(
+ "type", "other",
+ "foo", "fooVal",
+ "bar", 10
+ )),
+ new InSubType<>("other", new MissingKey("test"))
+ );
}
}
diff --git a/src/main/java/moe/nea/pcj/json/DuringKeyExtraction.java b/src/main/java/moe/nea/pcj/json/DuringKeyExtraction.java
new file mode 100644
index 0000000..859f98f
--- /dev/null
+++ b/src/main/java/moe/nea/pcj/json/DuringKeyExtraction.java
@@ -0,0 +1,4 @@
+package moe.nea.pcj.json;
+
+public record DuringKeyExtraction(JsonLikeError error) implements JsonLikeError {
+}
diff --git a/src/main/java/moe/nea/pcj/json/InSubType.java b/src/main/java/moe/nea/pcj/json/InSubType.java
new file mode 100644
index 0000000..ae62a73
--- /dev/null
+++ b/src/main/java/moe/nea/pcj/json/InSubType.java
@@ -0,0 +1,4 @@
+package moe.nea.pcj.json;
+
+public record InSubType<T>(T typeTag, JsonLikeError error) implements JsonLikeError {
+}
diff --git a/src/main/java/moe/nea/pcj/json/MapCodec.java b/src/main/java/moe/nea/pcj/json/MapCodec.java
index b18a639..9f343fd 100644
--- a/src/main/java/moe/nea/pcj/json/MapCodec.java
+++ b/src/main/java/moe/nea/pcj/json/MapCodec.java
@@ -13,24 +13,32 @@ public interface MapCodec<T, Format> {
default <O> MapCodec<? extends O, Format> dispatch(
Function<? super O, ? extends T> keyExtractor,
- Function<? super T, MapCodec<? extends O, Format>> codecGenerator
+ Function<? super T, Result<? extends MapCodec<? extends O, Format>, ? extends JsonLikeError>> codecGenerator
) {
// TODO: the codecGenerator function is not exactly typesafe. there should be some limit on keyExtractor and codecGenerator working in tandem
return new MapCodec<>() {
@Override
- public Result<O, JsonLikeError> decode(RecordView<Format> record, JsonLikeOperations<Format> ops) {
+ public Result<O, JsonLikeError> decode(RecordView<Format> record, JsonLikeOperations<Format> ops) { // TODO: map errors
return MapCodec.this.decode(record, ops)
- .map(codecGenerator::apply)
- .flatMap(codec -> codec.decode(record, ops));
+ .flatMap(key -> codecGenerator
+ .apply(key)
+ .<JsonLikeError>mapError(DuringKeyExtraction::new)
+ .flatMap(codec -> codec.decode(record, ops)
+ .<JsonLikeError>mapError(it -> new InSubType<>(key, it))));
}
@Override
public Result<RecordBuilder<Format>, JsonLikeError> encode(O value, JsonLikeOperations<Format> ops) {
var key = keyExtractor.apply(value);
- var codec = codecGenerator.apply(key);
- return MapCodec.this
- .encode(key, ops)
- .flatMap(keyEncoded -> ((MapCodec<O, Format>) codec).encode(value, ops).flatMap(keyEncoded::mergeWith));
+ return Result.<MapCodec<? extends O, Format>, JsonLikeError>cast(
+ codecGenerator.apply(key)
+ .mapError(DuringKeyExtraction::new))
+ .flatMap(codec -> MapCodec.this
+ .encode(key, ops)
+ .flatMap(keyEncoded -> ((MapCodec<O, Format>) codec)
+ .encode(value, ops)
+ .<JsonLikeError>mapError(it -> new InSubType<>(key, it))
+ .flatMap(keyEncoded::mergeWith)));
}
};
}
diff --git a/src/main/java/moe/nea/pcj/json/UnknownSubtype.java b/src/main/java/moe/nea/pcj/json/UnknownSubtype.java
new file mode 100644
index 0000000..942a7dc
--- /dev/null
+++ b/src/main/java/moe/nea/pcj/json/UnknownSubtype.java
@@ -0,0 +1,10 @@
+package moe.nea.pcj.json;
+
+import java.util.Set;
+
+public record UnknownSubtype<T>(T actual, Set<T> expectedTypes) implements JsonLikeError {
+ @SafeVarargs
+ public UnknownSubtype(T actual, T... expected) {
+ this(actual, Set.of(expected));
+ }
+}