Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 1 | package eu.mulk.jgvariant.ostree; |
| 2 | |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 3 | import java.nio.ByteBuffer; |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 4 | |
| 5 | /** An operation in a static delta. */ |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 6 | public sealed interface DeltaOperation { |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 7 | |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 8 | record OpenSpliceAndCloseMeta(long offset, long size) implements DeltaOperation {} |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 9 | |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 10 | record OpenSpliceAndCloseReal(long offset, long size, long modeOffset, long xattrOffset) |
| 11 | implements DeltaOperation {} |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 12 | |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 13 | record Open(long size, long modeOffset, long xattrOffset) implements DeltaOperation {} |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 14 | |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 15 | record Write(long offset, long size) implements DeltaOperation {} |
| 16 | |
| 17 | record SetReadSource(long offset) implements DeltaOperation {} |
| 18 | |
| 19 | record UnsetReadSource() implements DeltaOperation {} |
| 20 | |
| 21 | record Close() implements DeltaOperation {} |
| 22 | |
| 23 | record BsPatch(long offset, long size) implements DeltaOperation {} |
| 24 | |
| 25 | static DeltaOperation readFrom(ByteBuffer byteBuffer, ObjectType objectType) { |
| 26 | byte opcode = byteBuffer.get(); |
| 27 | return switch (DeltaOperationType.valueOf(opcode)) { |
| 28 | case OPEN_SPLICE_AND_CLOSE -> { |
| 29 | if (objectType == ObjectType.FILE || objectType == ObjectType.PAYLOAD_LINK) { |
| 30 | long modeOffset = readVarint64(byteBuffer); |
| 31 | long xattrOffset = readVarint64(byteBuffer); |
| 32 | long size = readVarint64(byteBuffer); |
| 33 | long offset = readVarint64(byteBuffer); |
| 34 | yield new OpenSpliceAndCloseReal(offset, size, modeOffset, xattrOffset); |
| 35 | } else { |
| 36 | long size = readVarint64(byteBuffer); |
| 37 | long offset = readVarint64(byteBuffer); |
| 38 | yield new OpenSpliceAndCloseMeta(offset, size); |
| 39 | } |
| 40 | } |
| 41 | case OPEN -> { |
| 42 | long modeOffset = readVarint64(byteBuffer); |
| 43 | long xattrOffset = readVarint64(byteBuffer); |
| 44 | long size = readVarint64(byteBuffer); |
| 45 | yield new Open(size, modeOffset, xattrOffset); |
| 46 | } |
| 47 | case WRITE -> { |
| 48 | long size = readVarint64(byteBuffer); |
| 49 | long offset = readVarint64(byteBuffer); |
| 50 | yield new Write(offset, size); |
| 51 | } |
| 52 | case SET_READ_SOURCE -> { |
| 53 | long offset = readVarint64(byteBuffer); |
| 54 | yield new SetReadSource(offset); |
| 55 | } |
| 56 | case UNSET_READ_SOURCE -> new UnsetReadSource(); |
| 57 | case CLOSE -> new Close(); |
| 58 | case BSPATCH -> { |
| 59 | long offset = readVarint64(byteBuffer); |
| 60 | long size = readVarint64(byteBuffer); |
| 61 | yield new BsPatch(offset, size); |
| 62 | } |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 63 | }; |
| 64 | } |
Matthias Andreas Benkard | c981cde | 2021-12-30 20:37:39 +0100 | [diff] [blame] | 65 | |
| 66 | /** |
| 67 | * Reads a Protobuf varint from a byte buffer. |
| 68 | * |
| 69 | * <p>Varint64 encoding is little-endian and works by using the lower 7 bits of each byte as the |
| 70 | * payload and the 0x80 bit as an indicator of whether the varint continues. |
| 71 | */ |
| 72 | private static long readVarint64(ByteBuffer byteBuffer) { |
| 73 | long acc = 0L; |
| 74 | |
| 75 | for (int i = 0; i < 10; ++i) { |
| 76 | long b = byteBuffer.get(); |
| 77 | acc |= (b & 0x7F) << (i * 7); |
| 78 | if ((b & 0x80) == 0) { |
| 79 | break; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | return acc; |
| 84 | } |
Matthias Andreas Benkard | 0511464 | 2021-12-29 21:51:29 +0100 | [diff] [blame] | 85 | } |