jvgariant-ostree: Correctly deserialize delta operations.
Change-Id: Ic6659d7ea5e9411220571c33979e29471cec897e
diff --git a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaPartPayload.java b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaPartPayload.java
index ed0f4ff..4e2587f 100644
--- a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaPartPayload.java
+++ b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaPartPayload.java
@@ -7,6 +7,7 @@
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.ArrayList;
import java.util.List;
import org.tukaani.xz.XZInputStream;
@@ -31,15 +32,6 @@
ByteString rawDataSource,
List<DeltaOperation> operations) {
- private static final Decoder<DeltaPartPayload> DECODER =
- Decoder.ofStructure(
- DeltaPartPayload.class,
- Decoder.ofArray(FileMode.decoder()),
- Decoder.ofArray(Decoder.ofArray(Xattr.decoder())),
- ByteString.decoder(),
- ByteString.decoder().map(DeltaPartPayload::parseDeltaOperationList))
- .contramap(DeltaPartPayload::preparse);
-
private static ByteBuffer preparse(ByteBuffer byteBuffer) {
byte compressionByte = byteBuffer.get(0);
var dataSlice = byteBuffer.slice(1, byteBuffer.limit() - 1);
@@ -65,25 +57,40 @@
};
}
- private static List<DeltaOperation> parseDeltaOperationList(ByteString byteString) {
- return byteString.stream().map(DeltaOperation::valueOf).toList();
+ private static List<DeltaOperation> parseDeltaOperationList(
+ ByteString byteString, List<ObjectType> objectTypes) {
+ List<DeltaOperation> deltaOperations = new ArrayList<>();
+ var byteBuffer = ByteBuffer.wrap(byteString.bytes());
+ int objectIndex = 0;
+
+ while (byteBuffer.hasRemaining()) {
+ var currentOperation = DeltaOperation.readFrom(byteBuffer, objectTypes.get(objectIndex));
+ deltaOperations.add(currentOperation);
+ if (currentOperation instanceof DeltaOperation.Close
+ || currentOperation instanceof DeltaOperation.OpenSpliceAndCloseMeta
+ || currentOperation instanceof DeltaOperation.OpenSpliceAndCloseReal) {
+ ++objectIndex;
+ }
+ }
+
+ return deltaOperations;
}
/**
* A file mode triple (UID, GID, and permission bits).
*
- * @param uid
- * @param gid
- * @param mode
+ * @param uid the user ID that owns the file.
+ * @param gid the group ID that owns the file.
+ * @param mode the POSIX permission bits.
*/
public record FileMode(int uid, int gid, int mode) {
private static final Decoder<FileMode> DECODER =
Decoder.ofStructure(
FileMode.class,
- Decoder.ofInt().withByteOrder(ByteOrder.LITTLE_ENDIAN),
- Decoder.ofInt().withByteOrder(ByteOrder.LITTLE_ENDIAN),
- Decoder.ofInt().withByteOrder(ByteOrder.LITTLE_ENDIAN));
+ Decoder.ofInt().withByteOrder(ByteOrder.BIG_ENDIAN),
+ Decoder.ofInt().withByteOrder(ByteOrder.BIG_ENDIAN),
+ Decoder.ofInt().withByteOrder(ByteOrder.BIG_ENDIAN));
/**
* Acquires a {@link Decoder} for the enclosing type.
@@ -98,12 +105,18 @@
/**
* Acquires a {@link Decoder} for the enclosing type.
*
- * <p>FIXME: The first byte is actually a compression byte: {@code 0} for none, {@code 'x'} for
- * LZMA.
- *
* @return a possibly shared {@link Decoder}.
*/
- public static Decoder<DeltaPartPayload> decoder() {
- return DECODER;
+ public static Decoder<DeltaPartPayload> decoder(DeltaMetaEntry deltaMetaEntry) {
+ var objectTypes =
+ deltaMetaEntry.objects().stream().map(DeltaMetaEntry.DeltaObject::objectType).toList();
+ return Decoder.ofStructure(
+ DeltaPartPayload.class,
+ Decoder.ofArray(FileMode.decoder()),
+ Decoder.ofArray(Decoder.ofArray(Xattr.decoder())),
+ ByteString.decoder(),
+ ByteString.decoder()
+ .map(byteString -> parseDeltaOperationList(byteString, objectTypes)))
+ .contramap(DeltaPartPayload::preparse);
}
}