From 4fdad152ba3a1b37eb45e657d59d15c8f73ae45c Mon Sep 17 00:00:00 2001 From: Andrew <3199649+abaranec@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:43:46 -0400 Subject: [PATCH] feat: Extract Codec & friends from Util into separate modules (#5727) This fixes #5726 by removing ObjectCodec and ObjectDecoder, their implementations, as well as CodecCache and it's exception from the Util module and into their own separate packages, codec-base, codec-builtin and codec-cache. --- codec/api/build.gradle | 10 ++++ codec/api/gradle.properties | 1 + .../io/deephaven/util/codec/ObjectCodec.java | 6 +- .../deephaven/util/codec/ObjectDecoder.java | 8 ++- codec/builtin/build.gradle | 17 ++++++ codec/builtin/gradle.properties | 1 + .../deephaven/util/codec/BigDecimalCodec.java | 20 +++---- .../deephaven/util/codec/BigIntegerCodec.java | 7 +-- .../io/deephaven/util/codec/CodecUtil.java | 59 ++----------------- .../util/codec/ExternalizableCodec.java | 11 ++-- .../deephaven/util/codec/LocalDateCodec.java | 5 +- .../deephaven/util/codec/LocalTimeCodec.java | 5 +- .../io/deephaven/util/codec/MapCodec.java | 11 ++-- .../util/codec/SerializableCodec.java | 5 +- .../util/codec/SimpleByteArrayCodec.java | 9 +-- .../util/codec/StringBooleanMapCodec.java | 0 .../util/codec/StringDoubleMapCodec.java | 0 .../util/codec/StringFloatMapCodec.java | 0 .../util/codec/StringIntMapCodec.java | 0 .../util/codec/StringKeyedMapCodec.java | 6 +- .../util/codec/StringLongMapCodec.java | 0 .../util/codec/StringStringMapCodec.java | 5 +- .../codec/UTF8StringAsByteArrayCodec.java | 5 +- .../util/codec/ZonedDateTimeCodec.java | 8 +-- .../util/codec/BigDecimalCodecTest.java | 0 .../util/codec/BigIntegerCodecTest.java | 0 .../util/codec/LocalDateCodecTest.java | 0 .../util/codec/LocalTimeCodecTest.java | 0 .../util/codec/ZonedDateTimeCodecTest.java | 4 +- codec/cache/build.gradle | 12 ++++ codec/cache/gradle.properties | 1 + .../io/deephaven/util/codec/CodecCache.java | 32 +--------- .../util/codec/CodecCacheException.java | 0 engine/chunk/build.gradle | 7 ++- engine/table/build.gradle | 3 + extensions/parquet/base/build.gradle | 1 + extensions/parquet/table/build.gradle | 5 +- settings.gradle | 7 +++ 38 files changed, 116 insertions(+), 155 deletions(-) create mode 100644 codec/api/build.gradle create mode 100644 codec/api/gradle.properties rename {Util => codec/api}/src/main/java/io/deephaven/util/codec/ObjectCodec.java (89%) rename {Util => codec/api}/src/main/java/io/deephaven/util/codec/ObjectDecoder.java (90%) create mode 100644 codec/builtin/build.gradle create mode 100644 codec/builtin/gradle.properties rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java (92%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java (90%) rename Util/src/main/java/io/deephaven/util/EncodingUtil.java => codec/builtin/src/main/java/io/deephaven/util/codec/CodecUtil.java (54%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java (84%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/LocalDateCodec.java (97%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java (97%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/MapCodec.java (93%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/SerializableCodec.java (93%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java (88%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringBooleanMapCodec.java (100%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringDoubleMapCodec.java (100%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringFloatMapCodec.java (100%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringIntMapCodec.java (100%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java (88%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringLongMapCodec.java (100%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java (89%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java (93%) rename {Util => codec/builtin}/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java (90%) rename {Util => codec/builtin}/src/test/java/io/deephaven/util/codec/BigDecimalCodecTest.java (100%) rename {Util => codec/builtin}/src/test/java/io/deephaven/util/codec/BigIntegerCodecTest.java (100%) rename {Util => codec/builtin}/src/test/java/io/deephaven/util/codec/LocalDateCodecTest.java (100%) rename {Util => codec/builtin}/src/test/java/io/deephaven/util/codec/LocalTimeCodecTest.java (100%) rename {Util => codec/builtin}/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java (97%) create mode 100644 codec/cache/build.gradle create mode 100644 codec/cache/gradle.properties rename {Util => codec/cache}/src/main/java/io/deephaven/util/codec/CodecCache.java (69%) rename {Util => codec/cache}/src/main/java/io/deephaven/util/codec/CodecCacheException.java (100%) diff --git a/codec/api/build.gradle b/codec/api/build.gradle new file mode 100644 index 00000000000..8de35953673 --- /dev/null +++ b/codec/api/build.gradle @@ -0,0 +1,10 @@ +plugins { + id 'java-library' + id 'io.deephaven.project.register' +} + +description 'Codec API: The base package for column codecs' + +dependencies { + compileOnly libs.jetbrains.annotations +} diff --git a/codec/api/gradle.properties b/codec/api/gradle.properties new file mode 100644 index 00000000000..c186bbfdde1 --- /dev/null +++ b/codec/api/gradle.properties @@ -0,0 +1 @@ +io.deephaven.project.ProjectType=JAVA_PUBLIC diff --git a/Util/src/main/java/io/deephaven/util/codec/ObjectCodec.java b/codec/api/src/main/java/io/deephaven/util/codec/ObjectCodec.java similarity index 89% rename from Util/src/main/java/io/deephaven/util/codec/ObjectCodec.java rename to codec/api/src/main/java/io/deephaven/util/codec/ObjectCodec.java index e1c96338778..def0542d264 100644 --- a/Util/src/main/java/io/deephaven/util/codec/ObjectCodec.java +++ b/codec/api/src/main/java/io/deephaven/util/codec/ObjectCodec.java @@ -24,14 +24,12 @@ public interface ObjectCodec extends ObjectDecoder { /** * Encode the specified input as an array of bytes. Note that it is up to the implementation how to encode null - * inputs. The use of a zero-length byte array (e.g. - * {@link io.deephaven.datastructures.util.CollectionUtil#ZERO_LENGTH_BYTE_ARRAY}) is strongly encouraged. + * inputs. The use of a zero-length byte array is strongly encouraged. * * @param input The input object, possibly null * @return The output byte array */ - @NotNull - byte[] encode(@Nullable TYPE input); + byte @NotNull [] encode(@Nullable TYPE input); /** * Does this codec support encoding of null values? diff --git a/Util/src/main/java/io/deephaven/util/codec/ObjectDecoder.java b/codec/api/src/main/java/io/deephaven/util/codec/ObjectDecoder.java similarity index 90% rename from Util/src/main/java/io/deephaven/util/codec/ObjectDecoder.java rename to codec/api/src/main/java/io/deephaven/util/codec/ObjectDecoder.java index 72728684abd..033a7b876f4 100644 --- a/Util/src/main/java/io/deephaven/util/codec/ObjectDecoder.java +++ b/codec/api/src/main/java/io/deephaven/util/codec/ObjectDecoder.java @@ -3,7 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.base.verify.Assert; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,7 +35,7 @@ public interface ObjectDecoder { * @return The output object, possibly null */ @Nullable - TYPE decode(@NotNull byte[] input, int offset, int length); + TYPE decode(byte @NotNull [] input, int offset, int length); /** * Decode an object from a ByteBuffer. The position of the input buffer may or may not be modified by this method. @@ -72,6 +71,9 @@ default TYPE decode(@NotNull final ByteBuffer buffer) { */ default void checkWidth(int actualWidth) throws IllegalArgumentException { final int expectedWidth = expectedObjectWidth(); - Assert.eq(expectedWidth, "expectedWidth", actualWidth, "actualWidth"); + if (expectedWidth != actualWidth) { + throw new IllegalArgumentException( + "Expected width `" + expectedWidth + "` does not match actual width `" + actualWidth + "`"); + } } } diff --git a/codec/builtin/build.gradle b/codec/builtin/build.gradle new file mode 100644 index 00000000000..055cd8de79e --- /dev/null +++ b/codec/builtin/build.gradle @@ -0,0 +1,17 @@ +plugins { + id 'java-library' + id 'io.deephaven.project.register' +} + +description 'Codec Builtin: Deephaven builtin codec implementations' + +dependencies { + api project(":codec-api") + + implementation project(":Base") + implementation project(":engine-query-constants") + + compileOnly libs.jetbrains.annotations + + testImplementation libs.junit4 +} diff --git a/codec/builtin/gradle.properties b/codec/builtin/gradle.properties new file mode 100644 index 00000000000..c186bbfdde1 --- /dev/null +++ b/codec/builtin/gradle.properties @@ -0,0 +1 @@ +io.deephaven.project.ProjectType=JAVA_PUBLIC diff --git a/Util/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java similarity index 92% rename from Util/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java index 697b9acfa50..2f0d9fcdfa2 100644 --- a/Util/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/BigDecimalCodec.java @@ -3,7 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.datastructures.util.CollectionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -73,18 +72,18 @@ public BigDecimalCodec(@Nullable String arguments) { try { int _precision = 0, _scale = 0; // zero indicates unlimited precision/scale, variable width encoding boolean _strict = true; - if (arguments != null && arguments.trim().length() > 0) { + if (arguments != null && !arguments.trim().isEmpty()) { final String[] tokens = arguments.split(","); - if (tokens.length > 0 && tokens[0].trim().length() > 0) { + if (tokens.length > 0 && !tokens[0].trim().isEmpty()) { _precision = Integer.parseInt(tokens[0].trim()); if (_precision < 1) { throw new IllegalArgumentException("Specified precision must be >= 1"); } } - if (tokens.length > 1 && tokens[1].trim().length() > 0) { + if (tokens.length > 1 && !tokens[1].trim().isEmpty()) { _scale = Integer.parseInt(tokens[1].trim()); } - if (tokens.length > 2 && tokens[2].trim().length() > 0) { + if (tokens.length > 2 && !tokens[2].trim().isEmpty()) { String mode = tokens[2].trim(); switch (mode.toLowerCase()) { case "allowrounding": @@ -141,13 +140,12 @@ private void init() { final byte[] unscaledZero = BigDecimal.ZERO.unscaledValue().toByteArray(); zeroBytes = new byte[Integer.BYTES + unscaledZero.length]; Arrays.fill(zeroBytes, (byte) 0); - nullBytes = CollectionUtil.ZERO_LENGTH_BYTE_ARRAY; + nullBytes = CodecUtil.ZERO_LENGTH_BYTE_ARRAY; } } - @NotNull @Override - public byte[] encode(@Nullable final BigDecimal input) { + public byte @NotNull [] encode(@Nullable final BigDecimal input) { if (input == null) { return nullBytes; } @@ -173,7 +171,7 @@ public byte[] encode(@Nullable final BigDecimal input) { // (i.e. too high a scale requires reducing precision to "make room") if ((value.precision() > this.precision || value.scale() > scale)) { if (strict) { - throw new IllegalArgumentException("Unable to encode value " + value.toString() + " with precision " + throw new IllegalArgumentException("Unable to encode value " + value + " with precision " + precision + " scale " + scale); } final int targetPrecision = Math.min(precision, value.precision() - Math.max(0, value.scale() - scale)); @@ -194,7 +192,7 @@ public byte[] encode(@Nullable final BigDecimal input) { // copy unscaled bytes to proper size array final byte[] unscaledValue = value.unscaledValue().toByteArray(); if (unscaledValue.length >= bytes.length) { // unscaled value must be at most one less than length of our buffer - throw new IllegalArgumentException("Value " + input.toString() + " is too large to encode with precision " + throw new IllegalArgumentException("Value " + input + " is too large to encode with precision " + precision + " and scale " + scale); } @@ -213,7 +211,7 @@ public byte[] encode(@Nullable final BigDecimal input) { @Nullable @Override - public BigDecimal decode(@NotNull final byte[] input, final int offset, final int length) { + public BigDecimal decode(final byte @NotNull [] input, final int offset, final int length) { // variable size value if (precision == 0) { diff --git a/Util/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java similarity index 90% rename from Util/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java index 024632e66cd..f9b19918cfe 100644 --- a/Util/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/BigIntegerCodec.java @@ -32,7 +32,7 @@ public BigIntegerCodec(@Nullable String arguments) { // noinspection ConstantConditions try { int _precision = 0; // zero indicates unlimited precision, variable width encoding - if (arguments != null && arguments.trim().length() > 0) { + if (arguments != null && !arguments.trim().isEmpty()) { _precision = Integer.parseInt(arguments.trim()); if (_precision < 1) { throw new IllegalArgumentException("Specified precision must be >= 1"); @@ -61,9 +61,8 @@ public int getScale() { return 0; } - @NotNull @Override - public byte[] encode(@Nullable final BigInteger input) { + public byte @NotNull [] encode(@Nullable final BigInteger input) { return input == null ? codec.encodedNullValue() : codec.encode(new BigDecimal(input)); @@ -71,7 +70,7 @@ public byte[] encode(@Nullable final BigInteger input) { @Nullable @Override - public BigInteger decode(@NotNull final byte[] input, final int offset, final int length) { + public BigInteger decode(final byte @NotNull [] input, final int offset, final int length) { final BigDecimal bd = codec.decode(input, offset, length); return bd == null ? null : bd.toBigInteger(); } diff --git a/Util/src/main/java/io/deephaven/util/EncodingUtil.java b/codec/builtin/src/main/java/io/deephaven/util/codec/CodecUtil.java similarity index 54% rename from Util/src/main/java/io/deephaven/util/EncodingUtil.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/CodecUtil.java index 81009c7774d..27c02c81625 100644 --- a/Util/src/main/java/io/deephaven/util/EncodingUtil.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/CodecUtil.java @@ -1,10 +1,9 @@ // // Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending // -package io.deephaven.util; +package io.deephaven.util.codec; import io.deephaven.base.string.EncodingInfo; -import org.apache.commons.io.ByteOrderMark; import org.jetbrains.annotations.NotNull; import java.nio.BufferOverflowException; @@ -12,63 +11,13 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; -import java.util.Arrays; -public class EncodingUtil { - @SuppressWarnings("WeakerAccess") - public static final ByteOrderMark[] EMPTY_BOM_ARRAY = new ByteOrderMark[0]; +class CodecUtil { + public static final byte[] ZERO_LENGTH_BYTE_ARRAY = new byte[0]; - /** - * Get the {@link EncodingInfo} associated with a particular {@link Charset} - * - * @param charSet The charset - * @return the matching {@link EncodingInfo} - * @throws IllegalArgumentException if there is no associated encoding - */ - @NotNull - public static EncodingInfo getEncodingInfoForCharset(@NotNull Charset charSet) throws IllegalArgumentException { - return getEncodingInfoForCharset(charSet.name()); - } - - /** - * Get the {@link EncodingInfo} associated with a particular charset name - * - * @param charsetName the charset - * @return the matching {@link EncodingInfo} - * @throws IllegalArgumentException if there is no associated encoding - */ - public static EncodingInfo getEncodingInfoForCharset(@NotNull String charsetName) { - return Arrays.stream(EncodingInfo.values()) - .filter(info -> info.getCharset().name().equals(charsetName)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("No EncodingInfo for " + charsetName)); - } - - /** - * Get an array containing the possible {@link ByteOrderMark byte order marks} that could be present within a file - * of the specified encoding. This is intended for use with {@link org.apache.commons.io.input.BOMInputStream} - * - * @param encoding The encoding. - * @return An array containing the possible {@link ByteOrderMark BOMs} for the encoding. - */ - @NotNull - public static ByteOrderMark[] getBOMsForEncoding(EncodingInfo encoding) { - switch (encoding) { - case UTF_8: - return new ByteOrderMark[] {ByteOrderMark.UTF_8}; - case UTF_16BE: - return new ByteOrderMark[] {ByteOrderMark.UTF_16BE}; - case UTF_16LE: - return new ByteOrderMark[] {ByteOrderMark.UTF_16LE}; - case UTF_16: - return new ByteOrderMark[] {ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE}; - } - - return EMPTY_BOM_ARRAY; - } + private CodecUtil() {} /** * Encode the given string in UTF-8 format into the given ByteBuffer. The string is encoded as an int length diff --git a/Util/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java similarity index 84% rename from Util/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java index eb2d42a2d9c..79585c8fc3b 100644 --- a/Util/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/ExternalizableCodec.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; import java.io.*; +import java.lang.reflect.InvocationTargetException; public class ExternalizableCodec implements ObjectCodec { @@ -21,9 +22,8 @@ public ExternalizableCodec(String className) { } } - @NotNull @Override - public byte[] encode(@Nullable T input) { + public byte @NotNull [] encode(@Nullable T input) { if (input == null) { throw new UnsupportedOperationException(getClass() + " does not support null input"); } @@ -55,16 +55,17 @@ public int getScale() { @Nullable @Override - public T decode(@NotNull byte[] input, int offset, int length) { + public T decode(byte @NotNull [] input, int offset, int length) { try { final ByteArrayInputStream byteInput = new ByteArrayInputStream(input, offset, length); final ObjectInputStream objectInput = new ObjectInputStream(byteInput); - T result = externalizableClass.newInstance(); + T result = externalizableClass.getDeclaredConstructor().newInstance(); result.readExternal(objectInput); return result; } catch (IOException e) { throw new UncheckedIOException(e); - } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) { + } catch (IllegalAccessException | InstantiationException | ClassNotFoundException | InvocationTargetException + | NoSuchMethodException e) { throw new RuntimeException(e); } } diff --git a/Util/src/main/java/io/deephaven/util/codec/LocalDateCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/LocalDateCodec.java similarity index 97% rename from Util/src/main/java/io/deephaven/util/codec/LocalDateCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/LocalDateCodec.java index 3870fa3ac57..20f60c42dd3 100644 --- a/Util/src/main/java/io/deephaven/util/codec/LocalDateCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/LocalDateCodec.java @@ -104,9 +104,8 @@ public int getScale() { return 0; } - @NotNull @Override - public byte[] encode(@Nullable final LocalDate input) { + public byte @NotNull [] encode(@Nullable final LocalDate input) { if (input == null) { if (nullBytes != null) { return nullBytes; @@ -157,7 +156,7 @@ public byte[] encode(@Nullable final LocalDate input) { @Nullable @Override - public LocalDate decode(@NotNull final byte[] input, final int offset, final int length) { + public LocalDate decode(final byte @NotNull [] input, final int offset, final int length) { final int year, month, dayOfMonth; if (input[offset] == NULL_INDICATOR) { return null; diff --git a/Util/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java similarity index 97% rename from Util/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java index 24aa7a9784c..013ebd01de4 100644 --- a/Util/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/LocalTimeCodec.java @@ -99,9 +99,8 @@ public int getScale() { return 0; } - @NotNull @Override - public byte[] encode(@Nullable final LocalTime input) { + public byte @NotNull [] encode(@Nullable final LocalTime input) { if (input == null) { if (nullBytes != null) { @@ -130,7 +129,7 @@ public byte[] encode(@Nullable final LocalTime input) { @Nullable @Override - public LocalTime decode(@NotNull final byte[] input, final int offset, final int length) { + public LocalTime decode(final byte @NotNull [] input, final int offset, final int length) { // test for null indicator (leading bit) if ((input[offset] & NULL_INDICATOR) != 0) { return null; diff --git a/Util/src/main/java/io/deephaven/util/codec/MapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/MapCodec.java similarity index 93% rename from Util/src/main/java/io/deephaven/util/codec/MapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/MapCodec.java index 2c1c85cae69..45dbd324b09 100644 --- a/Util/src/main/java/io/deephaven/util/codec/MapCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/MapCodec.java @@ -3,7 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.datastructures.util.CollectionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,7 +22,6 @@ */ @SuppressWarnings("unused") public abstract class MapCodec implements ObjectCodec> { - private static final byte[] nullBytes = CollectionUtil.ZERO_LENGTH_BYTE_ARRAY; private static final byte[] zeroBytes = new byte[4]; private static final int MINIMUM_SCRATCH_CAPACITY = 4096; @@ -47,13 +45,12 @@ public int getScale() { return 0; } - @NotNull @Override - public byte[] encode(@Nullable final Map input) { + public byte @NotNull [] encode(@Nullable final Map input) { if (input == null) { - return nullBytes; + return CodecUtil.ZERO_LENGTH_BYTE_ARRAY; } - if (input.size() == 0) { + if (input.isEmpty()) { return zeroBytes; } @@ -137,7 +134,7 @@ public Map decode(@NotNull final ByteBuffer byteBuffer) { @Nullable @Override - public Map decode(@NotNull final byte[] input, final int offset, final int length) { + public Map decode(final byte @NotNull [] input, final int offset, final int length) { if (input.length == 0) { return null; } diff --git a/Util/src/main/java/io/deephaven/util/codec/SerializableCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/SerializableCodec.java similarity index 93% rename from Util/src/main/java/io/deephaven/util/codec/SerializableCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/SerializableCodec.java index b9570299a49..9cd08f24abf 100644 --- a/Util/src/main/java/io/deephaven/util/codec/SerializableCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/SerializableCodec.java @@ -21,9 +21,8 @@ private SerializableCodec() {} public SerializableCodec(@SuppressWarnings("unused") String dummy) {} - @NotNull @Override - public byte[] encode(@Nullable T input) { + public byte @NotNull [] encode(@Nullable T input) { try { final ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); final ObjectOutputStream objectOutput = new ObjectOutputStream(byteOutput); @@ -52,7 +51,7 @@ public int getScale() { @Nullable @Override - public T decode(@NotNull byte[] input, int offset, int length) { + public T decode(byte @NotNull [] input, int offset, int length) { try { final ByteArrayInputStream byteInput = new ByteArrayInputStream(input, offset, length); final ObjectInputStream objectInput = new ObjectInputStream(byteInput); diff --git a/Util/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java similarity index 88% rename from Util/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java index 8bf70622a03..1dae95849ff 100644 --- a/Util/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/SimpleByteArrayCodec.java @@ -3,7 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.datastructures.util.CollectionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,9 +42,8 @@ public SimpleByteArrayCodec(@Nullable final String arguments) { expectedWidth = size; } - @NotNull @Override - public byte[] encode(@Nullable final byte[] input) { + public byte @NotNull [] encode(final byte @Nullable [] input) { if (input == null) { throw new IllegalArgumentException(SimpleByteArrayCodec.class.getSimpleName() + " cannot encode nulls"); } @@ -69,11 +67,10 @@ public int getScale() { return 0; } - @Nullable @Override - public byte[] decode(@NotNull final byte[] input, final int offset, final int length) { + public byte @Nullable [] decode(final byte @NotNull [] input, final int offset, final int length) { if (input.length == 0) { - return CollectionUtil.ZERO_LENGTH_BYTE_ARRAY; + return CodecUtil.ZERO_LENGTH_BYTE_ARRAY; } final byte[] output = new byte[length]; System.arraycopy(input, offset, output, 0, length); diff --git a/Util/src/main/java/io/deephaven/util/codec/StringBooleanMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringBooleanMapCodec.java similarity index 100% rename from Util/src/main/java/io/deephaven/util/codec/StringBooleanMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringBooleanMapCodec.java diff --git a/Util/src/main/java/io/deephaven/util/codec/StringDoubleMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringDoubleMapCodec.java similarity index 100% rename from Util/src/main/java/io/deephaven/util/codec/StringDoubleMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringDoubleMapCodec.java diff --git a/Util/src/main/java/io/deephaven/util/codec/StringFloatMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringFloatMapCodec.java similarity index 100% rename from Util/src/main/java/io/deephaven/util/codec/StringFloatMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringFloatMapCodec.java diff --git a/Util/src/main/java/io/deephaven/util/codec/StringIntMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringIntMapCodec.java similarity index 100% rename from Util/src/main/java/io/deephaven/util/codec/StringIntMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringIntMapCodec.java diff --git a/Util/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java similarity index 88% rename from Util/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java index 50650f1668d..a38124e360a 100644 --- a/Util/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/StringKeyedMapCodec.java @@ -3,8 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.util.EncodingUtil; - import java.nio.ByteBuffer; import java.util.Map; @@ -36,11 +34,11 @@ int estimateSize(Map input) { @Override String decodeKey(ByteBuffer byteBuffer) { - return EncodingUtil.getUtf8String(byteBuffer); + return CodecUtil.getUtf8String(byteBuffer); } @Override void encodeKey(ByteBuffer scratch, String key) { - EncodingUtil.putUtf8String(scratch, key); + CodecUtil.putUtf8String(scratch, key); } } diff --git a/Util/src/main/java/io/deephaven/util/codec/StringLongMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringLongMapCodec.java similarity index 100% rename from Util/src/main/java/io/deephaven/util/codec/StringLongMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringLongMapCodec.java diff --git a/Util/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java similarity index 89% rename from Util/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java index f85a6914759..4229d583460 100644 --- a/Util/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/StringStringMapCodec.java @@ -3,7 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.util.EncodingUtil; import org.jetbrains.annotations.Nullable; import java.nio.ByteBuffer; @@ -40,11 +39,11 @@ int getValueSize() { @Override String decodeValue(ByteBuffer byteBuffer) { - return EncodingUtil.getUtf8String(byteBuffer); + return CodecUtil.getUtf8String(byteBuffer); } @Override void encodeValue(ByteBuffer scratch, String value) { - EncodingUtil.putUtf8String(scratch, value); + CodecUtil.putUtf8String(scratch, value); } } diff --git a/Util/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java similarity index 93% rename from Util/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java index 5f32d7568d9..df29640baee 100644 --- a/Util/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/UTF8StringAsByteArrayCodec.java @@ -44,9 +44,8 @@ public UTF8StringAsByteArrayCodec(@Nullable final String arguments) { expectedWidth = size; } - @NotNull @Override - public byte[] encode(@Nullable final String input) { + public byte @NotNull [] encode(@Nullable final String input) { if (input == null) { throw new IllegalArgumentException( UTF8StringAsByteArrayCodec.class.getSimpleName() + " cannot encode nulls"); @@ -71,7 +70,7 @@ public int getScale() { @Nullable @Override - public String decode(@NotNull final byte[] input, final int offset, final int length) { + public String decode(final byte @NotNull [] input, final int offset, final int length) { return new String(input, offset, length, StandardCharsets.UTF_8); } diff --git a/Util/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java b/codec/builtin/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java similarity index 90% rename from Util/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java rename to codec/builtin/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java index e5092332dcf..c928ff6b71f 100644 --- a/Util/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java +++ b/codec/builtin/src/main/java/io/deephaven/util/codec/ZonedDateTimeCodec.java @@ -3,7 +3,6 @@ // package io.deephaven.util.codec; -import io.deephaven.datastructures.util.CollectionUtil; import io.deephaven.util.QueryConstants; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,11 +18,10 @@ public class ZonedDateTimeCodec implements ObjectCodec { public ZonedDateTimeCodec(String args) {} - @NotNull @Override - public byte[] encode(@Nullable ZonedDateTime input) { + public byte @NotNull [] encode(@Nullable ZonedDateTime input) { if (input == null) { - return CollectionUtil.ZERO_LENGTH_BYTE_ARRAY; + return CodecUtil.ZERO_LENGTH_BYTE_ARRAY; } final int bufSize = computeSize(input); @@ -40,7 +38,7 @@ public byte[] encode(@Nullable ZonedDateTime input) { @Nullable @Override - public ZonedDateTime decode(@NotNull byte[] input, int offset, int length) { + public ZonedDateTime decode(byte @NotNull [] input, int offset, int length) { if (length == 0) { return null; } diff --git a/Util/src/test/java/io/deephaven/util/codec/BigDecimalCodecTest.java b/codec/builtin/src/test/java/io/deephaven/util/codec/BigDecimalCodecTest.java similarity index 100% rename from Util/src/test/java/io/deephaven/util/codec/BigDecimalCodecTest.java rename to codec/builtin/src/test/java/io/deephaven/util/codec/BigDecimalCodecTest.java diff --git a/Util/src/test/java/io/deephaven/util/codec/BigIntegerCodecTest.java b/codec/builtin/src/test/java/io/deephaven/util/codec/BigIntegerCodecTest.java similarity index 100% rename from Util/src/test/java/io/deephaven/util/codec/BigIntegerCodecTest.java rename to codec/builtin/src/test/java/io/deephaven/util/codec/BigIntegerCodecTest.java diff --git a/Util/src/test/java/io/deephaven/util/codec/LocalDateCodecTest.java b/codec/builtin/src/test/java/io/deephaven/util/codec/LocalDateCodecTest.java similarity index 100% rename from Util/src/test/java/io/deephaven/util/codec/LocalDateCodecTest.java rename to codec/builtin/src/test/java/io/deephaven/util/codec/LocalDateCodecTest.java diff --git a/Util/src/test/java/io/deephaven/util/codec/LocalTimeCodecTest.java b/codec/builtin/src/test/java/io/deephaven/util/codec/LocalTimeCodecTest.java similarity index 100% rename from Util/src/test/java/io/deephaven/util/codec/LocalTimeCodecTest.java rename to codec/builtin/src/test/java/io/deephaven/util/codec/LocalTimeCodecTest.java diff --git a/Util/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java b/codec/builtin/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java similarity index 97% rename from Util/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java rename to codec/builtin/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java index 6c17e3cba49..5564ab4f660 100644 --- a/Util/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java +++ b/codec/builtin/src/test/java/io/deephaven/util/codec/ZonedDateTimeCodecTest.java @@ -3,6 +3,7 @@ // package io.deephaven.util.codec; +import org.junit.Assert; import org.junit.Test; import java.time.Instant; @@ -10,7 +11,6 @@ import java.time.ZonedDateTime; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; public class ZonedDateTimeCodecTest { private void roundTripWithOffset(final ZonedDateTime value, final int offset) { @@ -42,7 +42,7 @@ public void testMax() { roundTripWithOffset(ZonedDateTime.ofInstant( Instant.ofEpochSecond(ZonedDateTimeCodec.MAX_CONVERTIBLE_SECONDS + 1), ZoneId.of("America/New_York")), 0); - fail(); + Assert.fail(); } catch (IllegalArgumentException ignored) { } diff --git a/codec/cache/build.gradle b/codec/cache/build.gradle new file mode 100644 index 00000000000..d28f2793e9c --- /dev/null +++ b/codec/cache/build.gradle @@ -0,0 +1,12 @@ +plugins { + id 'java-library' + id 'io.deephaven.project.register' +} + +description 'Codec Cache: Deephaven Codec Cache' + +dependencies { + api project(":codec-api") + + compileOnly libs.jetbrains.annotations +} diff --git a/codec/cache/gradle.properties b/codec/cache/gradle.properties new file mode 100644 index 00000000000..c186bbfdde1 --- /dev/null +++ b/codec/cache/gradle.properties @@ -0,0 +1 @@ +io.deephaven.project.ProjectType=JAVA_PUBLIC diff --git a/Util/src/main/java/io/deephaven/util/codec/CodecCache.java b/codec/cache/src/main/java/io/deephaven/util/codec/CodecCache.java similarity index 69% rename from Util/src/main/java/io/deephaven/util/codec/CodecCache.java rename to codec/cache/src/main/java/io/deephaven/util/codec/CodecCache.java index ee920c5171d..10c2517090f 100644 --- a/Util/src/main/java/io/deephaven/util/codec/CodecCache.java +++ b/codec/cache/src/main/java/io/deephaven/util/codec/CodecCache.java @@ -3,25 +3,19 @@ // package io.deephaven.util.codec; -import io.deephaven.base.verify.Require; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.ZonedDateTime; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * Cache for {@link ObjectCodec} instances. */ public enum CodecCache { - DEFAULT; /** @@ -34,7 +28,7 @@ private static class Item { private Item(@NotNull final String className, @Nullable final String arguments) { - Require.neqNull(className, "className"); + Objects.requireNonNull(className); final Class codecClass; try { @@ -79,26 +73,4 @@ public synchronized ObjectCodec getCodec(@NotNull final String clas .computeIfAbsent(className, (cn) -> new HashMap<>()) .computeIfAbsent(arguments, (a) -> new Item(className, a)).codec; } - - /** - * Get the default {@link ObjectCodec} class to use for the given column type. - * - * @param dataType The column data type - * @return The name of the default {@link ObjectCodec} subclass to use for encoding the given type - */ - public static String getDefaultCodecClass(@NotNull final Class dataType) { - if (dataType.equals(LocalDate.class)) { - return LocalDateCodec.class.getName(); - } else if (dataType.equals(LocalTime.class)) { - return LocalTimeCodec.class.getName(); - } else if (dataType.equals(BigDecimal.class)) { - return BigDecimalCodec.class.getName(); - } else if (dataType.equals(BigInteger.class)) { - return BigIntegerCodec.class.getName(); - } else if (dataType.equals(ZonedDateTime.class)) { - return ZonedDateTimeCodec.class.getName(); - } else { - return null; - } - } } diff --git a/Util/src/main/java/io/deephaven/util/codec/CodecCacheException.java b/codec/cache/src/main/java/io/deephaven/util/codec/CodecCacheException.java similarity index 100% rename from Util/src/main/java/io/deephaven/util/codec/CodecCacheException.java rename to codec/cache/src/main/java/io/deephaven/util/codec/CodecCacheException.java diff --git a/engine/chunk/build.gradle b/engine/chunk/build.gradle index c883653c1ed..f359693611c 100644 --- a/engine/chunk/build.gradle +++ b/engine/chunk/build.gradle @@ -7,12 +7,13 @@ description 'Engine Chunks: Array-like data structures for dense, efficient data dependencies { api project(':Util') + api project(':codec-api:') implementation project(':Base') testImplementation libs.junit4 - testRuntimeOnly project(':log-to-slf4j'), - project(path: ':configs'), - project(path: ':test-configs') + testRuntimeOnly project(':log-to-slf4j') + testRuntimeOnly project(path: ':configs') + testRuntimeOnly project(path: ':test-configs') testRuntimeOnly libs.slf4j.simple } diff --git a/engine/table/build.gradle b/engine/table/build.gradle index fe9be770f49..0cf5fe712d5 100644 --- a/engine/table/build.gradle +++ b/engine/table/build.gradle @@ -21,6 +21,7 @@ dependencies { api project(':deephaven-jpy-ext') api project(':hotspot') api project(':IO') + api project(':codec-api') implementation project(':DHProcess') implementation project(':engine-function') @@ -28,6 +29,8 @@ dependencies { implementation project(':Configuration') implementation project(':log-factory') implementation project(':Stats') + implementation project(':codec-builtin') + implementation project(':codec-cache') implementation libs.f4b6a3.uuid.creator // TODO(deephaven-core#3204): t-digest 3.3 appears to have higher errors than 3.2 diff --git a/extensions/parquet/base/build.gradle b/extensions/parquet/base/build.gradle index 9a71ac9382c..7b63f37014b 100644 --- a/extensions/parquet/base/build.gradle +++ b/extensions/parquet/base/build.gradle @@ -7,6 +7,7 @@ description 'Parquet Base: Libraries for working with Parquet files' dependencies { api project(':util-channel') + api project(':codec-api') implementation libs.parquet.hadoop diff --git a/extensions/parquet/table/build.gradle b/extensions/parquet/table/build.gradle index caec0e66a29..5b7d43ddf67 100644 --- a/extensions/parquet/table/build.gradle +++ b/extensions/parquet/table/build.gradle @@ -24,6 +24,7 @@ dependencies { api project(':engine-api') api project(':engine-stringset') api project(':engine-table') + api project(':codec-api') implementation project(':extensions-parquet-base') implementation libs.parquet.hadoop @@ -32,9 +33,11 @@ dependencies { implementation project(':extensions-csv') implementation project(':log-factory') implementation project(':Configuration') - implementation libs.commons.lang3 implementation project(':Util') + implementation project(':codec-builtin') + implementation project(':codec-cache') + implementation libs.commons.lang3 implementation libs.commons.text implementation libs.commons.compress diff --git a/settings.gradle b/settings.gradle index deef79359aa..9db07a453c4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -415,6 +415,13 @@ include ':clock-impl' include ':sql' +include(':codec-api') +project(':codec-api').projectDir = file('codec/api') +include(':codec-builtin') +project(':codec-builtin').projectDir = file('codec/builtin') +include(':codec-cache') +project(':codec-cache').projectDir = file('codec/cache') + file("${rootDir}/docker/registry").list().each { name -> if (file("${rootDir}/docker/registry/${name}/build.gradle").exists()) { include(":docker-${name}")