Skip to content

Commit d54c751

Browse files
committed
allow no config for BytesCodec
1 parent acd8cc0 commit d54c751

5 files changed

Lines changed: 72 additions & 30 deletions

File tree

src/main/java/dev/zarr/zarrjava/core/codec/core/BytesCodec.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,44 @@
11
package dev.zarr.zarrjava.core.codec.core;
22

33
import com.fasterxml.jackson.annotation.JsonValue;
4+
import dev.zarr.zarrjava.ZarrException;
45
import dev.zarr.zarrjava.core.codec.ArrayBytesCodec;
56
import ucar.ma2.*;
67

78
import java.nio.ByteBuffer;
89
import java.nio.ByteOrder;
910

1011
public abstract class BytesCodec extends ArrayBytesCodec {
11-
protected abstract ByteOrder getByteOrder();
12+
protected abstract ByteOrder getByteOrder() throws ZarrException;
1213

1314
@Override
14-
public Array decode(ByteBuffer chunkBytes) {
15-
chunkBytes.order(getByteOrder());
16-
DataType dtype = arrayMetadata.dataType.getMA2DataType();
17-
int[] shape = arrayMetadata.chunkShape;
18-
19-
// Array.factory does not support boolean arrays directly from ByteBuffer
20-
if (dtype == DataType.BOOLEAN) {
21-
int size = chunkBytes.remaining();
22-
boolean[] bools = new boolean[size];
23-
for (int i = 0; i < size; i++) {
24-
bools[i] = chunkBytes.get(i) != 0;
25-
}
15+
public Array decode(ByteBuffer chunkBytes) throws ZarrException {
16+
ByteOrder order = ByteOrder.BIG_ENDIAN; // Default for 1-byte types
17+
if (arrayMetadata.dataType.getByteCount() > 1)
18+
order = getByteOrder();
19+
chunkBytes.order(order);
20+
DataType dtype = arrayMetadata.dataType.getMA2DataType();
21+
int[] shape = arrayMetadata.chunkShape;
22+
23+
// Array.factory does not support boolean arrays directly from ByteBuffer
24+
if (dtype == DataType.BOOLEAN) {
25+
int size = chunkBytes.remaining();
26+
boolean[] bools = new boolean[size];
27+
for (int i = 0; i < size; i++) {
28+
bools[i] = chunkBytes.get(i) != 0;
29+
}
2630

27-
Index index = Index.factory(shape);
28-
return Array.factory(DataType.BOOLEAN, index, bools);
31+
Index index = Index.factory(shape);
32+
return Array.factory(DataType.BOOLEAN, index, bools);
33+
}
34+
return Array.factory(dtype, shape, chunkBytes);
2935
}
3036

31-
return Array.factory(dtype, shape, chunkBytes);
32-
}
3337
@Override
34-
public ByteBuffer encode(Array chunkArray) {
35-
ByteOrder order = getByteOrder();
38+
public ByteBuffer encode(Array chunkArray) throws ZarrException {
39+
ByteOrder order = ByteOrder.BIG_ENDIAN; // Default for 1-byte types
40+
if (arrayMetadata.dataType.getByteCount() > 1)
41+
order = getByteOrder();
3642

3743
// Boolean
3844
if (chunkArray instanceof ArrayBoolean) {
@@ -94,6 +100,10 @@ public ByteOrder getByteOrder() {
94100
throw new RuntimeException("Unreachable");
95101
}
96102
}
103+
104+
public static Endian nativeOrder() {
105+
return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? LITTLE : BIG;
106+
}
97107
}
98108

99109
}

src/main/java/dev/zarr/zarrjava/v3/codec/CodecBuilder.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,21 @@ public CodecBuilder withTranspose(int[] order) {
6767
}
6868

6969
public CodecBuilder withBytes(Endian endian) {
70-
codecs.add(new BytesCodec(new BytesCodec.Configuration(endian)));
70+
if (dataType.getByteCount() <= 1)
71+
codecs.add(new BytesCodec());
72+
else
73+
codecs.add(new BytesCodec(endian));
7174
return this;
7275
}
7376

7477
public CodecBuilder withBytes(String endian) {
7578
return withBytes(BytesCodec.Endian.valueOf(endian));
7679
}
7780

81+
public CodecBuilder withBytes() {
82+
return withBytes(Endian.nativeOrder());
83+
}
84+
7885
public CodecBuilder withGzip(int clevel) {
7986
try {
8087
codecs.add(new GzipCodec(new GzipCodec.Configuration(clevel)));

src/main/java/dev/zarr/zarrjava/v3/codec/core/BytesCodec.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
package dev.zarr.zarrjava.v3.codec.core;
22

33
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonInclude;
45
import com.fasterxml.jackson.annotation.JsonProperty;
56
import dev.zarr.zarrjava.ZarrException;
67
import dev.zarr.zarrjava.v3.codec.Codec;
78
import dev.zarr.zarrjava.v3.ArrayMetadata;
89

910
import java.nio.ByteOrder;
1011
import javax.annotation.Nonnull;
12+
import javax.annotation.Nullable;
1113

14+
@JsonInclude(JsonInclude.Include.NON_NULL)
1215
public class BytesCodec extends dev.zarr.zarrjava.core.codec.core.BytesCodec implements Codec {
1316

1417
public final String name = "bytes";
15-
@Nonnull
18+
@Nullable
1619
public final Configuration configuration;
1720

1821
@JsonCreator
1922
public BytesCodec(
20-
@Nonnull @JsonProperty(value = "configuration", required = true) Configuration configuration
23+
@JsonProperty(value = "configuration") Configuration configuration
2124
) {
2225
this.configuration = configuration;
2326
}
2427

28+
public BytesCodec() {
29+
this((Configuration) null);
30+
}
31+
2532
public BytesCodec(Endian endian) {
2633
this(new BytesCodec.Configuration(endian));
2734
}
@@ -33,7 +40,10 @@ public long computeEncodedSize(long inputByteLength,
3340
}
3441

3542
@Override
36-
protected ByteOrder getByteOrder() {
43+
protected ByteOrder getByteOrder() throws ZarrException {
44+
if (configuration == null) {
45+
throw new ZarrException("BytesCodec configuration is required to determine endianess.");
46+
}
3747
return configuration.endian.getByteOrder();
3848
}
3949

src/test/java/dev/zarr/zarrjava/ZarrPythonTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ static void assertIsTestdata(ucar.ma2.Array result, dev.zarr.zarrjava.core.DataT
150150

151151
static Stream<Object[]> compressorAndDataTypeProviderV3() {
152152
Stream<Object[]> datatypeTests = Stream.of(
153-
// DataType.BOOL,
154-
// DataType.INT8,
155-
// DataType.UINT8, // -> BUG: see https://github.com/zarr-developers/zarr-java/issues/27
153+
DataType.BOOL,
154+
DataType.INT8,
155+
DataType.UINT8,
156156
DataType.INT16,
157157
DataType.UINT16,
158158
DataType.INT32,
@@ -203,7 +203,7 @@ public void testReadV3(String codec, String codecParam, DataType dataType) throw
203203
Assertions.assertArrayEquals(new int[]{2, 4, 8}, array.metadata().chunkShape());
204204
Assertions.assertEquals(42, array.metadata().attributes.get("answer"));
205205

206-
assertIsTestdata(result, DataType.INT32);
206+
assertIsTestdata(result, dataType);
207207
}
208208

209209
@ParameterizedTest
@@ -266,7 +266,7 @@ public void testWriteV3(String codec, String codecParam, DataType dataType) thro
266266
Assertions.assertArrayEquals(new int[]{2, 4, 8}, readArray.metadata().chunkShape());
267267
Assertions.assertEquals("test_value", readArray.metadata().attributes.get("test_key"));
268268

269-
assertIsTestdata(result, DataType.INT32);
269+
assertIsTestdata(result, dataType);
270270

271271
//read in zarr_python
272272
run_python_script("zarr_python_read.py", codec, codecParam, dataType.name().toLowerCase(), storeHandle.toPath().toString());

src/test/java/dev/zarr/zarrjava/ZarrV3Test.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.zarr.zarrjava;
22

3+
import dev.zarr.zarrjava.v3.codec.Codec;
34
import dev.zarr.zarrjava.v3.codec.core.BloscCodec;
45
import dev.zarr.zarrjava.v3.codec.core.ShardingIndexedCodec;
56

@@ -569,6 +570,20 @@ public void testCreateGroup() throws ZarrException, IOException {
569570
Assertions.assertEquals("world", group.metadata.attributes.get("hello"));
570571
}
571572

572-
573-
573+
@Test
574+
public void testCodecWithoutConfiguration() throws ZarrException, IOException {
575+
StoreHandle storeHandle = new FilesystemStore(TESTOUTPUT).resolve("testCodecWithoutConfigurationV3");
576+
Array array = Array.create(storeHandle, Array.metadataBuilder()
577+
.withShape(10, 10)
578+
.withDataType(DataType.UINT8)
579+
.withChunkShape(5, 5)
580+
.withCodecs(CodecBuilder::withBytes)
581+
.build()
582+
);
583+
Assertions.assertTrue(storeHandle.resolve("zarr.json").exists());
584+
Codec bytesCodec = array.metadata().codecs[0];
585+
Assertions.assertInstanceOf(BytesCodec.class, bytesCodec);
586+
Assertions.assertNull(((BytesCodec) bytesCodec).configuration);
587+
// further todo: remove redundant "name" attribute from codec metadata serialization
588+
}
574589
}

0 commit comments

Comments
 (0)