jgvariant-ostree: Handle non-canonical endianness in static deltas.
Change-Id: I333fce6d6f4df995d6d965261bb66e50c116f02d
diff --git a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaFallback.java b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaFallback.java
index 46470d4..0967043 100644
--- a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaFallback.java
+++ b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaFallback.java
@@ -23,15 +23,21 @@
DeltaFallback.class,
Decoder.ofByte().map(ObjectType::valueOf),
Checksum.decoder(),
- Decoder.ofLong().withByteOrder(ByteOrder.LITTLE_ENDIAN), // FIXME: non-canonical
- Decoder.ofLong().withByteOrder(ByteOrder.LITTLE_ENDIAN)); // FIXME: non-canonical
+ Decoder.ofLong(),
+ Decoder.ofLong());
/**
* Acquires a {@link Decoder} for the enclosing type.
*
+ * <p><strong>Note:</strong> This decoder has an unspecified {@link ByteOrder}.
+ *
* @return a possibly shared {@link Decoder}.
*/
public static Decoder<DeltaFallback> decoder() {
return DECODER;
}
+
+ DeltaFallback byteSwapped() {
+ return new DeltaFallback(objectType, checksum, compressedSize, uncompressedSize);
+ }
}
diff --git a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaMetaEntry.java b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaMetaEntry.java
index 0eaea73..7269a80 100644
--- a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaMetaEntry.java
+++ b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaMetaEntry.java
@@ -49,10 +49,10 @@
private static final Decoder<DeltaMetaEntry> DECODER =
Decoder.ofStructure(
DeltaMetaEntry.class,
- Decoder.ofInt().withByteOrder(ByteOrder.LITTLE_ENDIAN), // FIXME: non-canonical
+ Decoder.ofInt(),
Checksum.decoder(),
- Decoder.ofLong().withByteOrder(ByteOrder.LITTLE_ENDIAN), // FIXME: non-canonical
- Decoder.ofLong().withByteOrder(ByteOrder.LITTLE_ENDIAN), // FIXME: non-canonical
+ Decoder.ofLong(),
+ Decoder.ofLong(),
Decoder.ofByteArray().map(DeltaMetaEntry::parseObjectList));
private static List<DeltaObject> parseObjectList(byte[] bytes) {
@@ -71,9 +71,16 @@
/**
* Acquires a {@link Decoder} for the enclosing type.
*
+ * <p><strong>Note:</strong> This decoder has an unspecified {@link ByteOrder}.
+ *
* @return a possibly shared {@link Decoder}.
*/
public static Decoder<DeltaMetaEntry> decoder() {
return DECODER;
}
+
+ DeltaMetaEntry byteSwapped() {
+ // FIXME
+ return new DeltaMetaEntry(version, checksum, compressedSize, uncompressedSize, objects);
+ }
}
diff --git a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaSuperblock.java b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaSuperblock.java
index edcf2bf..10b1661 100644
--- a/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaSuperblock.java
+++ b/jgvariant-ostree/src/main/java/eu/mulk/jgvariant/ostree/DeltaSuperblock.java
@@ -57,15 +57,41 @@
private static final Decoder<DeltaSuperblock> DECODER =
Decoder.ofStructure(
- DeltaSuperblock.class,
- Metadata.decoder(),
- Decoder.ofLong().withByteOrder(ByteOrder.BIG_ENDIAN),
- Checksum.decoder(),
- Checksum.decoder(),
- Commit.decoder(),
- Decoder.ofByteArray().map(DeltaSuperblock::parseDeltaNameList),
- Decoder.ofArray(DeltaMetaEntry.decoder()),
- Decoder.ofArray(DeltaFallback.decoder()));
+ DeltaSuperblock.class,
+ Metadata.decoder(),
+ Decoder.ofLong().withByteOrder(ByteOrder.BIG_ENDIAN),
+ Checksum.decoder(),
+ Checksum.decoder(),
+ Commit.decoder(),
+ Decoder.ofByteArray().map(DeltaSuperblock::parseDeltaNameList),
+ Decoder.ofArray(DeltaMetaEntry.decoder()).withByteOrder(ByteOrder.LITTLE_ENDIAN),
+ Decoder.ofArray(DeltaFallback.decoder()).withByteOrder(ByteOrder.LITTLE_ENDIAN))
+ .map(
+ deltaSuperblock -> {
+ // Fix up the endianness of the 'entries' and 'fallbacks' fields, which have
+ // unspecified byte order.
+ var endiannessMetadatum =
+ deltaSuperblock.metadata().fields().get("ostree.endianness");
+ if (endiannessMetadatum != null
+ && endiannessMetadatum.value() instanceof Byte endiannessByte
+ && endiannessByte == (byte) 'B') {
+ return deltaSuperblock.byteSwapped();
+ } else {
+ return deltaSuperblock;
+ }
+ });
+
+ private DeltaSuperblock byteSwapped() {
+ return new DeltaSuperblock(
+ metadata,
+ timestamp,
+ fromChecksum,
+ toChecksum,
+ commit,
+ dependencies,
+ entries.stream().map(DeltaMetaEntry::byteSwapped).toList(),
+ fallbacks.stream().map(DeltaFallback::byteSwapped).toList());
+ }
private static List<DeltaName> parseDeltaNameList(byte[] bytes) {
var byteBuffer = ByteBuffer.wrap(bytes);