aboutsummaryrefslogtreecommitdiff
path: root/jgvariant-core
diff options
context:
space:
mode:
Diffstat (limited to 'jgvariant-core')
-rw-r--r--jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java68
-rw-r--r--jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java2
-rw-r--r--jgvariant-core/src/main/java/module-info.java5
-rw-r--r--jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java27
4 files changed, 100 insertions, 2 deletions
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java
index d2f2403..fc11eab 100644
--- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java
+++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Decoder.java
@@ -12,6 +12,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.function.Function;
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;
import org.jetbrains.annotations.Nullable;
@@ -80,7 +81,7 @@ public abstract class Decoder<T> {
* @param byteOrder the byte order to use.
* @return a new, decorated {@link Decoder}.
*/
- public Decoder<T> withByteOrder(ByteOrder byteOrder) {
+ public final Decoder<T> withByteOrder(ByteOrder byteOrder) {
var delegate = this;
return new Decoder<>() {
@@ -103,6 +104,34 @@ public abstract class Decoder<T> {
}
/**
+ * Creates a new {@link Decoder} from an existing one by applying a function to the result.
+ *
+ * @param function the function to apply.
+ * @return a new, decorated {@link Decoder}.
+ * @see java.util.stream.Stream#map
+ */
+ public final <U> Decoder<U> map(Function<T, U> function) {
+ var delegate = this;
+
+ return new Decoder<>() {
+ @Override
+ public byte alignment() {
+ return delegate.alignment();
+ }
+
+ @Override
+ public @Nullable Integer fixedSize() {
+ return delegate.fixedSize();
+ }
+
+ @Override
+ public U decode(ByteBuffer byteSlice) {
+ return function.apply(delegate.decode(byteSlice));
+ }
+ };
+ }
+
+ /**
* Creates a {@link Decoder} for an {@code Array} type.
*
* @param elementDecoder a {@link Decoder} for the elements of the array.
@@ -114,6 +143,16 @@ public abstract class Decoder<T> {
}
/**
+ * Creates a {@link Decoder} for an {@code Array} type of element type {@code byte} into a
+ * primitive {@code byte[]} array.
+ *
+ * @return a new {@link Decoder}.
+ */
+ public static Decoder<byte[]> ofByteArray() {
+ return new ByteArrayDecoder();
+ }
+
+ /**
* Creates a {@link Decoder} for a {@code Maybe} type.
*
* @param elementDecoder a {@link Decoder} for the contained element.
@@ -299,6 +338,9 @@ public abstract class Decoder<T> {
var element = elementDecoder.decode(byteSlice.slice(i, elementSize));
elements.add(element);
}
+ } else if (byteSlice.limit() == 0) {
+ // A degenerate zero-length array of variable width.
+ elements = List.of();
} else {
// An array with aligned elements and a vector of framing offsets in the end.
int framingOffsetSize = byteCount(byteSlice.limit());
@@ -321,6 +363,30 @@ public abstract class Decoder<T> {
}
}
+ private static class ByteArrayDecoder extends Decoder<byte[]> {
+
+ private static final int ELEMENT_SIZE = 1;
+
+ @Override
+ public byte alignment() {
+ return ELEMENT_SIZE;
+ }
+
+ @Override
+ @Nullable
+ Integer fixedSize() {
+ return null;
+ }
+
+ @Override
+ public byte[] decode(ByteBuffer byteSlice) {
+ // A simple C-style array.
+ byte[] elements = new byte[byteSlice.limit() / ELEMENT_SIZE];
+ byteSlice.get(elements);
+ return elements;
+ }
+ }
+
private static class MaybeDecoder<U> extends Decoder<Optional<U>> {
private final Decoder<U> elementDecoder;
diff --git a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java
index d9de5f1..78e4bdd 100644
--- a/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java
+++ b/jgvariant-core/src/main/java/eu/mulk/jgvariant/core/Signature.java
@@ -43,7 +43,7 @@ public final class Signature {
return new Signature(signatureBytes);
}
- static Signature parse(String signatureString) throws ParseException {
+ public static Signature parse(String signatureString) throws ParseException {
var signatureBytes = ByteBuffer.wrap(signatureString.getBytes(StandardCharsets.US_ASCII));
return parse(signatureBytes);
}
diff --git a/jgvariant-core/src/main/java/module-info.java b/jgvariant-core/src/main/java/module-info.java
index a1830f6..0ef35cc 100644
--- a/jgvariant-core/src/main/java/module-info.java
+++ b/jgvariant-core/src/main/java/module-info.java
@@ -49,6 +49,10 @@
* <groupId>eu.mulk.jgvariant</groupId>
* <artifactId>jgvariant-core</artifactId>
* </dependency>
+ * <dependency>
+ * <groupId>eu.mulk.jgvariant</groupId>
+ * <artifactId>jgvariant-ostree</artifactId>
+ * </dependency>
*
* ...
* </dependencies>
@@ -65,6 +69,7 @@
*
* implementation(platform("eu.mulk.jgvariant:jgvariant-bom:0.1.4")
* implementation("eu.mulk.jgvariant:jgvariant-core")
+ * implementation("eu.mulk.jgvariant:jgvariant-ostree")
*
* ...
* }
diff --git a/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java b/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java
index 5cf1a1c..d72a1b6 100644
--- a/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java
+++ b/jgvariant-core/src/test/java/eu/mulk/jgvariant/core/DecoderTest.java
@@ -242,6 +242,26 @@ class DecoderTest {
}
@Test
+ void testPrimitiveByteArray() {
+ var data = new byte[] {0x04, 0x05, 0x06, 0x07};
+
+ var decoder = Decoder.ofByteArray();
+
+ assertArrayEquals(data, decoder.decode(ByteBuffer.wrap(data)));
+ }
+
+ @Test
+ void testPrimitiveByteArrayRecord() {
+ var data = new byte[] {0x04, 0x05, 0x06, 0x07};
+
+ record TestRecord(byte[] bytes) {}
+
+ var decoder = Decoder.ofStructure(TestRecord.class, Decoder.ofByteArray());
+
+ assertArrayEquals(data, decoder.decode(ByteBuffer.wrap(data)).bytes());
+ }
+
+ @Test
void testIntegerArray() {
var data = new byte[] {0x04, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00};
@@ -434,4 +454,11 @@ class DecoderTest {
var signature = Signature.parse(ByteBuffer.wrap(data));
assertEquals("(bynqiuxtdsogvmiai)", signature.toString());
}
+
+ @Test
+ void testMap() {
+ var data = new byte[] {0x0A, 0x0B, 0x0C};
+ var decoder = Decoder.ofByteArray().map(bytes -> bytes.length);
+ assertEquals(3, decoder.decode(ByteBuffer.wrap(data)));
+ }
}