Skip to content

Commit 9091817

Browse files
authored
Merge pull request #12 from asdf-format/eslavich-lz4-compressor
LZ4 compressor + generalize reference file testing
2 parents 7b491bc + 32eeb4f commit 9091817

23 files changed

Lines changed: 187 additions & 43 deletions

File tree

.github/workflows/publish.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@ jobs:
2828
run: mvn --batch-mode deploy
2929
env:
3030
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
32+
OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }}
33+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
34+
MAVEN_GPG_KEY: ${{ secrets.MAVEN_GPG_KEY }}

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ jobs:
3131
with:
3232
python-version: '3.12'
3333

34-
- name: Install test file generator requirements
34+
- name: Install reference file generator requirements
3535
run: |
36-
pip install asdf numpy
36+
pip install asdf numpy lz4
3737
3838
- name: Locate Python
3939
id: locate-python

asdf-compression-commons-compress/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<artifactId>asdf-compression-commons-compress</artifactId>
1111

1212
<name>asdf-compression-commons-compress</name>
13-
<description>Support for BZip2 and LZ4 Frame compressed blocks</description>
13+
<description>Support for BZip2 and LZ4 compressed blocks</description>
1414

1515
<dependencies>
1616
<dependency>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.asdfformat.asdf.io.compression;
2+
3+
import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorInputStream;
4+
import org.asdfformat.asdf.io.util.IOUtils;
5+
6+
import java.io.IOException;
7+
import java.nio.ByteBuffer;
8+
import java.nio.ByteOrder;
9+
10+
public class Lz4Compressor implements Compressor {
11+
public static final byte[] IDENTIFIER = {108, 122, 52, 0}; // 'lz4' + padding
12+
13+
@Override
14+
public byte[] getIdentifier() {
15+
return IDENTIFIER;
16+
}
17+
18+
@Override
19+
public long decompress(final ByteBuffer inputBuffer, final ByteBuffer outputBuffer) throws IOException {
20+
long bytesDecompressed = 0L;
21+
22+
while (inputBuffer.hasRemaining()) {
23+
inputBuffer.order(ByteOrder.BIG_ENDIAN);
24+
final int lz4BlockLength = inputBuffer.getInt() - 4;
25+
if (lz4BlockLength < 0) {
26+
throw new RuntimeException("LZ4 block length > " + Integer.MAX_VALUE + " not supported");
27+
}
28+
29+
// Discard the uncompressed data size written by the Python LZ4 bindings:
30+
inputBuffer.getInt();
31+
32+
final ByteBuffer lz4BlockInputBuffer = inputBuffer.duplicate();
33+
lz4BlockInputBuffer.limit(inputBuffer.position() + lz4BlockLength);
34+
35+
try (final ByteBufferInputStream byteBufferInputStream = new ByteBufferInputStream(lz4BlockInputBuffer);
36+
final BlockLZ4CompressorInputStream blockLZ4CompressorInputStream = new BlockLZ4CompressorInputStream(byteBufferInputStream)
37+
) {
38+
bytesDecompressed += IOUtils.transferTo(blockLZ4CompressorInputStream, outputBuffer);
39+
}
40+
41+
inputBuffer.position(inputBuffer.position() + lz4BlockLength);
42+
}
43+
44+
return bytesDecompressed;
45+
}
46+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.asdfformat.asdf.io.compression;
2+
3+
import org.asdfformat.asdf.Asdf;
4+
import org.asdfformat.asdf.AsdfFile;
5+
import org.asdfformat.asdf.io.compression.testing.CommonsCompressReferenceFileType;
6+
import org.asdfformat.asdf.ndarray.DoubleNdArray;
7+
import org.asdfformat.asdf.standard.AsdfStandardType;
8+
import org.asdfformat.asdf.testing.ReferenceFileUtils;
9+
import org.junit.jupiter.api.Tag;
10+
import org.junitpioneer.jupiter.cartesian.CartesianTest;
11+
12+
import java.io.IOException;
13+
import java.nio.file.Path;
14+
15+
import static org.asdfformat.asdf.io.compression.testing.TestCategories.REFERENCE_TESTS;
16+
import static org.junit.jupiter.api.Assertions.assertEquals;
17+
18+
@Tag(REFERENCE_TESTS)
19+
public class Lz4CompressorReferenceTest {
20+
@CartesianTest
21+
public void test1d(
22+
@CartesianTest.Enum(value = CommonsCompressReferenceFileType.class, names = {"NDARRAY_COMPRESSED_LZ4"}) final CommonsCompressReferenceFileType referenceFileType,
23+
@CartesianTest.Enum(AsdfStandardType.class) final AsdfStandardType asdfStandardType
24+
) throws IOException {
25+
final Path path = ReferenceFileUtils.getPath(referenceFileType, asdfStandardType.getVersion());
26+
27+
try (final AsdfFile asdfFile = Asdf.open(path)) {
28+
final DoubleNdArray doubleNdArray = asdfFile.getTree().get("arr").asNdArray().asDoubleNdArray();
29+
30+
for (int i = 0; i < 10; i++) {
31+
assertEquals(doubleNdArray.get(i), i);
32+
}
33+
}
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.asdfformat.asdf.io.compression.testing;
2+
3+
import org.asdfformat.asdf.testing.ReferenceFile;
4+
5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
8+
public enum CommonsCompressReferenceFileType implements ReferenceFile {
9+
NDARRAY_COMPRESSED_LZ4,
10+
;
11+
12+
@Override
13+
public String getName() {
14+
return name();
15+
}
16+
17+
@Override
18+
public InputStream openScript() throws IOException {
19+
return CommonsCompressReferenceFileType.class.getResourceAsStream(
20+
String.format("/test-file-scripts/%s.py", name().toLowerCase())
21+
);
22+
}
23+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.asdfformat.asdf.io.compression.testing;
2+
3+
public class TestCategories {
4+
public static final String REFERENCE_TESTS = "reference-tests";
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
af["arr"] = np.arange(0, 10, dtype=np.float64)
2+
3+
af.set_array_compression(af["arr"], "lz4")

asdf-core/src/main/java/org/asdfformat/asdf/io/compression/Compressors.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ public class Compressors {
2222
.identifier("bzp2".getBytes(StandardCharsets.UTF_8))
2323
.moduleName("asdf-compression-commons-compress")
2424
.build(),
25+
OptionalCompressor.builder()
26+
.className("org.asdfformat.asdf.io.compression.Lz4Compressor")
27+
.identifier(new byte[] {108, 122, 52, 0})
28+
.moduleName("asdf-compression-commons-compress")
29+
.build(),
2530
OptionalCompressor.builder()
2631
.className("org.asdfformat.asdf.io.compression.Lz4FrameCompressor")
2732
.identifier("lz4f".getBytes(StandardCharsets.UTF_8))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.asdfformat.asdf.testing;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
6+
public interface ReferenceFile {
7+
String getName();
8+
InputStream openScript() throws IOException;
9+
}

0 commit comments

Comments
 (0)