From 5eea18ea497d4bc11466b2bd875582ba26f188f5 Mon Sep 17 00:00:00 2001
From: Linnea Gräf <nea@nea.moe>
Date: Thu, 14 Nov 2024 02:59:11 +0100
Subject: Add lists

---
 src/main/java/moe/nea/pcj/Result.java         |  1 +
 src/main/java/moe/nea/pcj/json/AtIndex.java   |  4 +++
 src/main/java/moe/nea/pcj/json/JsonCodec.java | 40 +++++++++++++++++++++++++++
 src/main/java/moe/nea/pcj/json/MapCodec.java  |  4 +++
 4 files changed, 49 insertions(+)
 create mode 100644 src/main/java/moe/nea/pcj/json/AtIndex.java

(limited to 'src')

diff --git a/src/main/java/moe/nea/pcj/Result.java b/src/main/java/moe/nea/pcj/Result.java
index 22c94f9..af5398e 100644
--- a/src/main/java/moe/nea/pcj/Result.java
+++ b/src/main/java/moe/nea/pcj/Result.java
@@ -7,6 +7,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Consumer;
 import java.util.function.Function;
 
 public sealed interface Result<Good, Bad> permits Result.Ok, Result.Fail {
diff --git a/src/main/java/moe/nea/pcj/json/AtIndex.java b/src/main/java/moe/nea/pcj/json/AtIndex.java
new file mode 100644
index 0000000..ec01112
--- /dev/null
+++ b/src/main/java/moe/nea/pcj/json/AtIndex.java
@@ -0,0 +1,4 @@
+package moe.nea.pcj.json;
+
+public record AtIndex(int index, JsonLikeError error) implements JsonLikeError {
+}
diff --git a/src/main/java/moe/nea/pcj/json/JsonCodec.java b/src/main/java/moe/nea/pcj/json/JsonCodec.java
index 65f4a5e..6195bee 100644
--- a/src/main/java/moe/nea/pcj/json/JsonCodec.java
+++ b/src/main/java/moe/nea/pcj/json/JsonCodec.java
@@ -2,11 +2,51 @@ package moe.nea.pcj.json;
 
 import moe.nea.pcj.Codec;
 import moe.nea.pcj.Result;
+import moe.nea.pcj.Unit;
+
+import java.util.ArrayList;
+import java.util.List;
 
 public interface JsonCodec<T, Format> extends Codec<
 		T, Format, JsonLikeOperations<Format>,
 		JsonLikeError, JsonLikeError> {
 
+	default JsonCodec<List<T>, Format> listOf() {
+		return new JsonCodec<>() {
+			@Override
+			public Result<Format, JsonLikeError> encode(List<T> data, JsonLikeOperations<Format> ops) {
+				var list = ops.createList();
+				var erros = new ArrayList<JsonLikeError>();
+				for (int i = 0; i < data.size(); i++) {
+					var datum = data.get(i);
+					final var index = i;
+					var result = JsonCodec.this.encode(datum, ops)
+					                           .mapError(it -> new AtIndex(index, it));
+					erros.addAll(result.errors());
+					result.valueOrPartial().ifPresent(list::add);
+				}
+				return Result.<Format, JsonLikeError>ok(list.complete()).appendErrors(erros);
+			}
+
+			@Override
+			public Result<List<T>, JsonLikeError> decode(Format format, JsonLikeOperations<Format> ops) {
+				var view = Result.<ListView<Format>, JsonLikeError>cast(ops.getList(format));
+				return view.flatMap(elements -> {
+					var acc = new ArrayList<T>(elements.length());
+					var errors = new ArrayList<JsonLikeError>();
+					for (int i = 0; i < elements.length(); i++) {
+						final var index = i;
+						var result = JsonCodec.this.decode(elements.getUnsafe(i), ops)
+						                           .mapError(it -> new AtIndex(index, it));
+						errors.addAll(result.errors());
+						result.valueOrPartial().ifPresent(acc::add);
+					}
+					return Result.<List<T>, JsonLikeError>ok(acc).appendErrors(errors);
+				});
+			}
+		};
+	}
+
 	default MapCodec<T, Format> fieldOf(String key) {
 		return new MapCodec<>() {
 			@Override
diff --git a/src/main/java/moe/nea/pcj/json/MapCodec.java b/src/main/java/moe/nea/pcj/json/MapCodec.java
index 468e4cf..4b76150 100644
--- a/src/main/java/moe/nea/pcj/json/MapCodec.java
+++ b/src/main/java/moe/nea/pcj/json/MapCodec.java
@@ -11,6 +11,10 @@ public interface MapCodec<T, Format> {
 
 	Result<RecordBuilder<Format>, JsonLikeError> encode(T value, JsonLikeOperations<Format> ops);
 
+	default JsonCodec<T, Format> codec() {
+		return RecordJoiners.join(withGetter(it -> it), it -> it);
+	}
+
 	default <O> RecordCodec<O, T, Format> withGetter(Function<O, T> getter) {
 		return new RecordCodec<>(this, getter);
 	}
-- 
cgit