package moe.nea.pcj.json; import moe.nea.pcj.Result; import java.util.function.Function; public interface MapCodec { Result decode( RecordView record, JsonLikeOperations ops); Result, JsonLikeError> encode(T value, JsonLikeOperations ops); default MapCodec dispatch( Function keyExtractor, Function> 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 decode(RecordView record, JsonLikeOperations ops) { return MapCodec.this.decode(record, ops) .map(codecGenerator::apply) .flatMap(codec -> codec.decode(record, ops)); } @Override public Result, JsonLikeError> encode(O value, JsonLikeOperations ops) { var key = keyExtractor.apply(value); var codec = codecGenerator.apply(key); return MapCodec.this .encode(key, ops) .flatMap(keyEncoded -> ((MapCodec) codec).encode(value, ops).flatMap(keyEncoded::mergeWith)); } }; } default JsonCodec codec() { return new JsonCodec<>() { @Override public Result decode(Format format, JsonLikeOperations ops) { return Result., JsonLikeError>cast(ops.getObject(format)) .flatMap(record -> MapCodec.this.decode(record, ops)); } @Override public Result encode(T data, JsonLikeOperations ops) { return Result.cast(MapCodec.this.encode(data, ops)).map(RecordBuilder::complete); } }; } default RecordCodec withGetter(Function getter) { return new RecordCodec<>(this, getter); } }