From 6edfaf4d717f97272b8807c06c54d7989a7c8ba6 Mon Sep 17 00:00:00 2001 From: Benjamin Marwell Date: Mon, 20 May 2019 18:17:54 +0200 Subject: [PATCH] Implement chunk decompression for #3. --- .../algo/unknown/UnknownAlgorithm.java | 7 +- .../compression/api/CompressionAlgorithm.java | 7 +- .../api/CompressionAlgorithmFactory.java | 7 +- .../api/err/DecompressionException.java | 10 +++ .../api/internal/ReflectionUtil.java | 9 ++- compression/compression-none/pom.xml | 24 +++++++ .../algo/none/NoneCompressionAlgorithm.java | 26 ++++++++ compression/compression-zstd/pom.xml | 33 ++++++++++ .../algo/zstd/ZStdCompressionAlgorithm.java | 49 ++++++++++++++ fileformat/pom.xml | 13 ++++ .../io/github/zchunk/fileformat/ZChunk.java | 65 ++++++++++++++++++- .../fileformat/ZChunkHeaderFactory.java | 7 +- .../fileformat/io/BoundedInputStream.java | 42 ++++++++++++ .../zchunk/fileformat/util/OffsetUtil.java | 4 ++ .../ZChunkCompressionSupportTest.java | 41 ++++++++++++ .../zchunk/fileformat/ZChunkFileTest.java | 21 +++++- pom.xml | 2 + 17 files changed, 348 insertions(+), 19 deletions(-) create mode 100644 compression/compression-api/src/main/java/io/github/zchunk/compression/api/err/DecompressionException.java create mode 100644 compression/compression-none/pom.xml create mode 100644 compression/compression-none/src/main/java/io/github/zchunk/compression/algo/none/NoneCompressionAlgorithm.java create mode 100644 compression/compression-zstd/pom.xml create mode 100644 compression/compression-zstd/src/main/java/io/github/zchunk/compression/algo/zstd/ZStdCompressionAlgorithm.java create mode 100644 fileformat/src/main/java/io/github/zchunk/fileformat/io/BoundedInputStream.java create mode 100644 fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkCompressionSupportTest.java diff --git a/compression/compression-api/src/main/java/io/github/zchunk/compression/algo/unknown/UnknownAlgorithm.java b/compression/compression-api/src/main/java/io/github/zchunk/compression/algo/unknown/UnknownAlgorithm.java index 987c411..9f38781 100644 --- a/compression/compression-api/src/main/java/io/github/zchunk/compression/algo/unknown/UnknownAlgorithm.java +++ b/compression/compression-api/src/main/java/io/github/zchunk/compression/algo/unknown/UnknownAlgorithm.java @@ -19,8 +19,9 @@ import io.github.zchunk.compressedint.CompressedInt; import io.github.zchunk.compressedint.CompressedIntFactory; import io.github.zchunk.compression.api.CompressionAlgorithm; +import io.github.zchunk.compression.api.err.DecompressionException; import java.io.InputStream; -import java.util.function.Function; +import java.util.function.BiFunction; public class UnknownAlgorithm implements CompressionAlgorithm { @@ -35,7 +36,7 @@ public String getName() { } @Override - public Function getOutputStreamSupplier() { - throw new UnsupportedOperationException("not implemented"); + public BiFunction getOutputStreamSupplier() { + throw new DecompressionException("Could not a valid decompressor implementation."); } } diff --git a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithm.java b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithm.java index e53b981..7833548 100644 --- a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithm.java +++ b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithm.java @@ -18,10 +18,8 @@ import io.github.zchunk.compressedint.CompressedInt; import java.io.InputStream; -import java.util.function.Function; -import org.immutables.value.Value; +import java.util.function.BiFunction; -@Value.Immutable public interface CompressionAlgorithm { /** @@ -41,6 +39,7 @@ public interface CompressionAlgorithm { /** * A method that will take in a stream and output an uncompressed stream. * @return a stream conversion method. + * @throws io.github.zchunk.compression.api.err.DecompressionException if an exception occurs. */ - Function getOutputStreamSupplier(); + BiFunction getOutputStreamSupplier(); } diff --git a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithmFactory.java b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithmFactory.java index 2870f0b..37dfed8 100644 --- a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithmFactory.java +++ b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/CompressionAlgorithmFactory.java @@ -19,6 +19,7 @@ import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; +import io.github.zchunk.compressedint.CompressedInt; import io.github.zchunk.compression.algo.unknown.UnknownAlgorithm; import io.github.zchunk.compression.api.internal.ReflectionUtil; import java.util.AbstractMap; @@ -43,7 +44,7 @@ private CompressionAlgorithmFactory() { private static Map.@Nullable Entry> mapEntryOrNull(final Class clazz) { return ReflectionUtil.newInstance(clazz) - .map(compInstance -> new AbstractMap.SimpleEntry<>(compInstance.getCompressionTypeValue().getLongValue(), clazz)) + .map(compInstance -> new AbstractMap.SimpleEntry<>(compInstance.getCompressionTypeValue().getUnsignedLongValue(), clazz)) .orElse(null); } @@ -72,6 +73,10 @@ private static Map> getTypeMappings() { return ResourceHolder.newInstance(ROOT_PACKAGE).getTypeMapping(); } + public static CompressionAlgorithm forType(final CompressedInt compressedInt) { + return forType(compressedInt.getLongValue()); + } + private static class ResourceHolder { diff --git a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/err/DecompressionException.java b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/err/DecompressionException.java new file mode 100644 index 0000000..f6121ee --- /dev/null +++ b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/err/DecompressionException.java @@ -0,0 +1,10 @@ +package io.github.zchunk.compression.api.err; + +public class DecompressionException extends RuntimeException { + + private static final long serialVersionUID = 8784156714006343592L; + + public DecompressionException(String message) { + super(message); + } +} diff --git a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/internal/ReflectionUtil.java b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/internal/ReflectionUtil.java index ae0d465..d1fe756 100644 --- a/compression/compression-api/src/main/java/io/github/zchunk/compression/api/internal/ReflectionUtil.java +++ b/compression/compression-api/src/main/java/io/github/zchunk/compression/api/internal/ReflectionUtil.java @@ -58,6 +58,7 @@ public static List> getClasses(final String rootPackage, final Clas .flatMap(Collection::stream) .collect(toList()); } catch (final IOException ioEx) { + LOG.log(Level.SEVERE, ioEx, () -> String.format("Unable to load classes in root package [%s].", rootPackage)); return emptyList(); } } @@ -106,10 +107,12 @@ private static List> findClasses(final String packageName, final Cl private static Optional> loadClass(final String packageName, final Class clazzType, final File file) { try { final Class aClass = Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)); - if (classImplementsCompressionAlgorithm(clazzType).test(aClass)) { + final boolean classImplementsType = classImplementsCompressionAlgorithm(clazzType).test(aClass); + + if (classImplementsType) { @SuppressWarnings("unchecked") final Class castedClass = (Class) aClass; - return Optional.ofNullable(castedClass); + return Optional.of(castedClass); } } catch (final ClassNotFoundException e) { LOG.log(Level.WARNING, e, () -> String.format("Class file [%s] found, but unable to create instance.", file.getAbsolutePath())); @@ -143,7 +146,7 @@ public static Optional newInstance(final Class clazz) { } public static Predicate> classImplementsCompressionAlgorithm(final Class type) { - return clazz -> getListFromArray(type.getInterfaces()).contains(type); + return clazz -> getListFromArray(clazz.getInterfaces()).contains(type); } } diff --git a/compression/compression-none/pom.xml b/compression/compression-none/pom.xml new file mode 100644 index 0000000..c77eec4 --- /dev/null +++ b/compression/compression-none/pom.xml @@ -0,0 +1,24 @@ + + + + zchunk-parent + io.github.zchunk + 1.0.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + zchunk-compression-none + + + + io.github.zchunk + compression-api + 1.0.0-SNAPSHOT + + + + + \ No newline at end of file diff --git a/compression/compression-none/src/main/java/io/github/zchunk/compression/algo/none/NoneCompressionAlgorithm.java b/compression/compression-none/src/main/java/io/github/zchunk/compression/algo/none/NoneCompressionAlgorithm.java new file mode 100644 index 0000000..5fe8ece --- /dev/null +++ b/compression/compression-none/src/main/java/io/github/zchunk/compression/algo/none/NoneCompressionAlgorithm.java @@ -0,0 +1,26 @@ +package io.github.zchunk.compression.algo.none; + +import io.github.zchunk.compressedint.CompressedInt; +import io.github.zchunk.compressedint.CompressedIntFactory; +import io.github.zchunk.compression.api.CompressionAlgorithm; + +import java.io.InputStream; +import java.util.function.BiFunction; + +public class NoneCompressionAlgorithm implements CompressionAlgorithm { + + @Override + public CompressedInt getCompressionTypeValue() { + return CompressedIntFactory.valueOf(0L); + } + + @Override + public String getName() { + return "none"; + } + + @Override + public BiFunction getOutputStreamSupplier() { + return (a, b) -> a; + } +} diff --git a/compression/compression-zstd/pom.xml b/compression/compression-zstd/pom.xml new file mode 100644 index 0000000..1310de8 --- /dev/null +++ b/compression/compression-zstd/pom.xml @@ -0,0 +1,33 @@ + + + + zchunk-parent + io.github.zchunk + 1.0.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + zchunk-compression-zstd + + + + io.github.zchunk + compression-api + 1.0.0-SNAPSHOT + + + + + + com.github.luben + zstd-jni + 1.4.0-1 + + + + + + \ No newline at end of file diff --git a/compression/compression-zstd/src/main/java/io/github/zchunk/compression/algo/zstd/ZStdCompressionAlgorithm.java b/compression/compression-zstd/src/main/java/io/github/zchunk/compression/algo/zstd/ZStdCompressionAlgorithm.java new file mode 100644 index 0000000..5872b56 --- /dev/null +++ b/compression/compression-zstd/src/main/java/io/github/zchunk/compression/algo/zstd/ZStdCompressionAlgorithm.java @@ -0,0 +1,49 @@ +package io.github.zchunk.compression.algo.zstd; + +import com.github.luben.zstd.ZstdInputStream; +import io.github.zchunk.compressedint.CompressedInt; +import io.github.zchunk.compressedint.CompressedIntFactory; +import io.github.zchunk.compression.api.CompressionAlgorithm; +import io.github.zchunk.compression.api.err.DecompressionException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.function.BiFunction; + +public class ZStdCompressionAlgorithm implements CompressionAlgorithm { + + private static final CompressedInt TWO = CompressedIntFactory.valueOf(2L); + private static final String ALGORITHM_NAME_ZSTD = "zstd"; + + @Override + public CompressedInt getCompressionTypeValue() { + return TWO; + } + + @Override + public String getName() { + return ALGORITHM_NAME_ZSTD; + } + + @Override + public BiFunction getOutputStreamSupplier() { + return createZstdInputStream(); + } + + private BiFunction createZstdInputStream() { + return (compressedInputStream, dict) -> { + try { + final ZstdInputStream zstdInputStream = new ZstdInputStream(compressedInputStream); + if (!Arrays.equals(new byte[0], dict)) { + zstdInputStream.setDict(dict); + } + + return zstdInputStream; + } catch (final IOException e) { + throw new DecompressionException("Unable to create input stream."); + } + }; + } + + +} diff --git a/fileformat/pom.xml b/fileformat/pom.xml index 8c0f914..cc67615 100644 --- a/fileformat/pom.xml +++ b/fileformat/pom.xml @@ -42,6 +42,19 @@ 1.0.0-SNAPSHOT + + + io.github.zchunk + zchunk-compression-none + 1.0.0-SNAPSHOT + test + + + io.github.zchunk + zchunk-compression-zstd + 1.0.0-SNAPSHOT + test + diff --git a/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunk.java b/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunk.java index 682c8e2..12efe3d 100644 --- a/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunk.java +++ b/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunk.java @@ -16,11 +16,21 @@ package io.github.zchunk.fileformat; +import io.github.zchunk.compression.api.CompressionAlgorithm; import io.github.zchunk.fileformat.err.InvalidFileException; +import io.github.zchunk.fileformat.io.BoundedInputStream; import io.github.zchunk.fileformat.util.ChecksumUtil; +import io.github.zchunk.fileformat.util.OffsetUtil; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.function.BiFunction; +import java.util.logging.Logger; -public class ZChunk { +public final class ZChunk { + + private static final Logger LOG = Logger.getLogger("io.github.zchunk.fileformat.ZChunk"); /** * Reads in a zchunk file. @@ -52,4 +62,57 @@ public static boolean validateFile(final File file) { && ChecksumUtil.isValidData(header, file); } + /** + * Get a chunk info item. + * + * @param header + * the header to extract the info from. + * @param chunkNumber + * the chunk number to extract. + * @return the ZChunk if it was found. + * @throws IllegalArgumentException + * if the chunk was not found. + */ + public static ZChunkHeaderChunkInfo getChunkInfo(final ZChunkHeader header, final long chunkNumber) { + return header.getIndex().getChunkInfoSortedByIndex().stream() + .filter(currChunk -> currChunk.getCurrentIndex() == chunkNumber) + .findFirst().orElseThrow(IllegalArgumentException::new); + } + + public static byte[] getDecompressedDict(final ZChunkHeader header, final File input) { + final long offset = OffsetUtil.getDictOffset(header); + final CompressionAlgorithm compressionAlgorithm = header.getPreface().getCompressionAlgorithm(); + final BiFunction decompressor = compressionAlgorithm.getOutputStreamSupplier(); + + try ( + final FileInputStream fis = new FileInputStream(input); + final InputStream decompressedStream = decompressor.apply(fis, new byte[0]) + ) { + fis.skip(offset); + final byte[] dictBuffer = new byte[header.getIndex().getUncompressedDictLength().getIntValue()]; + decompressedStream.read(dictBuffer); + return dictBuffer; + } catch (final IOException ioEx) { + final String message = String.format("Unable to read dictionary at offset [%d] from file [%s].", offset, input.getAbsolutePath()); + throw new IllegalArgumentException(message); + } + + } + + public static InputStream getDecompressedChunk(final ZChunkHeader header, + final File testFile, + final byte[] dict, + final long chunkNumber) throws IOException { + final long chunkOffset = OffsetUtil.getChunkOffset(header, chunkNumber); + final ZChunkHeaderChunkInfo chunk = getChunkInfo(header, chunkNumber); + final CompressionAlgorithm compressionAlgorithm = header.getPreface().getCompressionAlgorithm(); + final BiFunction decompressor = compressionAlgorithm.getOutputStreamSupplier(); + + // including skip + final long compressedBytesReadLimit = chunkOffset + chunk.getChunkLength().getLongValue(); + final BoundedInputStream fis = new BoundedInputStream(new FileInputStream(testFile), compressedBytesReadLimit); + fis.skip(chunkOffset); + + return decompressor.apply(fis, dict); + } } diff --git a/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunkHeaderFactory.java b/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunkHeaderFactory.java index d735c66..97ba3c6 100644 --- a/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunkHeaderFactory.java +++ b/fileformat/src/main/java/io/github/zchunk/fileformat/ZChunkHeaderFactory.java @@ -23,7 +23,6 @@ import io.github.zchunk.compressedint.CompressedIntFactory; import io.github.zchunk.compression.api.CompressionAlgorithm; import io.github.zchunk.compression.api.CompressionAlgorithmFactory; -import io.github.zchunk.compression.api.ImmutableCompressionAlgorithm; import io.github.zchunk.fileformat.err.InvalidFileException; import io.github.zchunk.fileformat.parser.ZChunkIndexParser; import io.github.zchunk.fileformat.parser.ZChunkLeadParser; @@ -157,11 +156,7 @@ private static ZChunkHeaderPreface getZChunkFileHeaderPrefaceFromParser(final ZC final CompressedInt prefaceFlagsInt = prefaceParser.readFlagsInt(); final Set flags = PrefaceFlag.getPrefaceFlags(prefaceFlagsInt); - final CompressionAlgorithm compressionAlgorithm = ImmutableCompressionAlgorithm.builder() - .compressionTypeValue(prefaceParser.readCompressionType()) - .name("unknown") - .outputStreamSupplier(a -> a) - .build(); + final CompressionAlgorithm compressionAlgorithm = CompressionAlgorithmFactory.forType(prefaceParser.readCompressionType()); return ImmutableZChunkHeaderPreface.builder() .totalDataChecksum(prefaceParser.readTotalDataCksum()) diff --git a/fileformat/src/main/java/io/github/zchunk/fileformat/io/BoundedInputStream.java b/fileformat/src/main/java/io/github/zchunk/fileformat/io/BoundedInputStream.java new file mode 100644 index 0000000..e883ea9 --- /dev/null +++ b/fileformat/src/main/java/io/github/zchunk/fileformat/io/BoundedInputStream.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018 The zchunk-java contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.zchunk.fileformat.io; + +import java.io.IOException; +import java.io.InputStream; + +public class BoundedInputStream extends InputStream { + + private final InputStream in; + private final long limit; + private long readCount = 0L; + + public BoundedInputStream(final InputStream in, final long limit) { + this.in = in; + this.limit = limit; + } + + @Override + public int read() throws IOException { + if (this.readCount >= this.limit) { + return -1; + } + + this.readCount++; + return this.in.read(); + } +} diff --git a/fileformat/src/main/java/io/github/zchunk/fileformat/util/OffsetUtil.java b/fileformat/src/main/java/io/github/zchunk/fileformat/util/OffsetUtil.java index 87949cc..3a9a5b2 100644 --- a/fileformat/src/main/java/io/github/zchunk/fileformat/util/OffsetUtil.java +++ b/fileformat/src/main/java/io/github/zchunk/fileformat/util/OffsetUtil.java @@ -89,4 +89,8 @@ public static long getChunkOffset(final ZChunkHeader zChunkHeader, final long ch return totalHeaderSize + dictLength.getLongValue() + chunkOffset; } + public static long getDictOffset(final ZChunkHeader zChunkHeader) { + return getTotalHeaderSize(zChunkHeader.getLead()); + } + } diff --git a/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkCompressionSupportTest.java b/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkCompressionSupportTest.java new file mode 100644 index 0000000..18f869f --- /dev/null +++ b/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkCompressionSupportTest.java @@ -0,0 +1,41 @@ +package io.github.zchunk.fileformat; + +import io.github.zchunk.compression.algo.none.NoneCompressionAlgorithm; +import io.github.zchunk.compression.algo.unknown.UnknownAlgorithm; +import io.github.zchunk.compression.algo.zstd.ZStdCompressionAlgorithm; +import io.github.zchunk.compression.api.CompressionAlgorithm; +import io.github.zchunk.compression.api.CompressionAlgorithmFactory; +import io.github.zchunk.compression.api.err.DecompressionException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ZChunkCompressionSupportTest { + + @Test + public void testCompressionSupport_unknown() { + final CompressionAlgorithm compressionAlgorithm = CompressionAlgorithmFactory.forType(4); + Assertions.assertAll( + () -> Assertions.assertEquals(UnknownAlgorithm.class, compressionAlgorithm.getClass()), + () -> Assertions.assertEquals("unknown", compressionAlgorithm.getName()), + () -> Assertions.assertThrows(DecompressionException.class, compressionAlgorithm::getOutputStreamSupplier) + ); + } + + @Test + public void testCompressionSupport_none() { + final CompressionAlgorithm compressionAlgorithm = CompressionAlgorithmFactory.forType(0L); + Assertions.assertAll( + () -> Assertions.assertEquals(NoneCompressionAlgorithm.class, compressionAlgorithm.getClass()), + () -> Assertions.assertEquals("none", compressionAlgorithm.getName()) + ); + } + + @Test + public void testCompressionSupport_zstd() { + final CompressionAlgorithm compressionAlgorithm = CompressionAlgorithmFactory.forType(2L); + Assertions.assertAll( + () -> Assertions.assertEquals(ZStdCompressionAlgorithm.class, compressionAlgorithm.getClass()), + () -> Assertions.assertEquals("zstd", compressionAlgorithm.getName()) + ); + } +} diff --git a/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkFileTest.java b/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkFileTest.java index 3ef12f1..ab30805 100644 --- a/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkFileTest.java +++ b/fileformat/src/test/java/io/github/zchunk/fileformat/ZChunkFileTest.java @@ -20,6 +20,9 @@ import io.github.zchunk.fileformat.util.ChecksumUtil; import io.github.zchunk.fileformat.util.OffsetUtil; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.logging.Logger; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -49,7 +52,8 @@ public void testFileFormat() { () -> testLead(header.getLead()), () -> testPreface(header.getPreface()), () -> testIndex(header.getIndex()), - () -> checkChecksum(header) + () -> checkChecksum(header), + () -> testDecompressDictOnFirstChunk(header, TEST_FILE) ); } @@ -105,4 +109,19 @@ private void testIndex(final ZChunkHeaderIndex index) { ); } + private void testDecompressDictOnFirstChunk(final ZChunkHeader header, final File testFile) { + final byte[] dict = ZChunk.getDecompressedDict(header, testFile); + final ZChunkHeaderChunkInfo chunkInfo = ZChunk.getChunkInfo(header, 0L); + final byte[] chunkBuffer = new byte[chunkInfo.getChunkUncompressedLength().getIntValue()]; + + try (final InputStream is = ZChunk.getDecompressedChunk(header, testFile, dict, 0L)) { + // only read the first few bytes to see if it works. + is.read(chunkBuffer, 0, 120); + } catch (final IOException ioEx) { + throw new RuntimeException(ioEx); + } + + final String readBytes = new String(chunkBuffer, StandardCharsets.UTF_8); + Assertions.assertTrue(readBytes.startsWith("")); + } } diff --git a/pom.xml b/pom.xml index e323281..b808a73 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,8 @@ compressedint compression/compression-api + compression/compression-none + compression/compression-zstd fileformat