Skip to content

Commit 29a8e8a

Browse files
dfa1claude
andauthored
refactor: drive ZstdStreamBuffer offsets from a MemoryLayout (#60)
Replace the hardcoded ZSTD_inBuffer/ZSTD_outBuffer struct layout (magic offsets OFF_PTR/OFF_SIZE/OFF_POS and BYTES = 24) with a named StructLayout and derive the total size, field handles, and offsets from it. Field access now goes through VarHandles obtained from the layout. Behavior-preserving. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3891697 commit 29a8e8a

1 file changed

Lines changed: 26 additions & 12 deletions

File tree

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
package io.github.dfa1.zstd;
22

33
import java.lang.foreign.Arena;
4+
import java.lang.foreign.MemoryLayout;
45
import java.lang.foreign.MemorySegment;
6+
import java.lang.invoke.VarHandle;
57

68
import static java.lang.foreign.ValueLayout.ADDRESS;
79
import static java.lang.foreign.ValueLayout.JAVA_LONG;
810

911
// Backing for ZSTD_inBuffer / ZSTD_outBuffer, which share a layout of a
10-
// void pointer then two size_t values. On LP64: ptr@0 (8), size@8 (8),
11-
// pos@16 (8) -> 24 bytes.
12+
// void pointer then two size_t values: { void* ptr; size_t size; size_t pos; }.
13+
// The struct shape, its total size and the field offsets are all derived from
14+
// LAYOUT below rather than hardcoded.
1215
final class ZstdStreamBuffer {
1316

14-
static final long BYTES = 24;
15-
private static final long OFF_PTR = 0;
16-
private static final long OFF_SIZE = 8;
17-
private static final long OFF_POS = 16;
17+
private static final MemoryLayout.PathElement PTR = MemoryLayout.PathElement.groupElement("ptr");
18+
private static final MemoryLayout.PathElement SIZE = MemoryLayout.PathElement.groupElement("size");
19+
private static final MemoryLayout.PathElement POS = MemoryLayout.PathElement.groupElement("pos");
20+
21+
private static final java.lang.foreign.StructLayout LAYOUT = MemoryLayout.structLayout(
22+
ADDRESS.withName("ptr"),
23+
JAVA_LONG.withName("size"),
24+
JAVA_LONG.withName("pos"));
25+
26+
static final long BYTES = LAYOUT.byteSize();
27+
28+
// Layout VarHandles have coordinates (MemorySegment, long base); we always pass base 0.
29+
private static final VarHandle PTR_HANDLE = LAYOUT.varHandle(PTR);
30+
private static final VarHandle SIZE_HANDLE = LAYOUT.varHandle(SIZE);
31+
private static final VarHandle POS_HANDLE = LAYOUT.varHandle(POS);
1832

1933
private final MemorySegment struct;
2034

2135
ZstdStreamBuffer(Arena arena) {
22-
this.struct = arena.allocate(BYTES);
36+
this.struct = arena.allocate(LAYOUT);
2337
}
2438

2539
MemorySegment segment() {
@@ -28,16 +42,16 @@ MemorySegment segment() {
2842

2943
/// Points the buffer at `buffer` with the given size and a fresh position of 0.
3044
void set(MemorySegment buffer, long size) {
31-
struct.set(ADDRESS, OFF_PTR, buffer);
32-
struct.set(JAVA_LONG, OFF_SIZE, size);
33-
struct.set(JAVA_LONG, OFF_POS, 0L);
45+
PTR_HANDLE.set(struct, 0L, buffer);
46+
SIZE_HANDLE.set(struct, 0L, size);
47+
POS_HANDLE.set(struct, 0L, 0L);
3448
}
3549

3650
long size() {
37-
return struct.get(JAVA_LONG, OFF_SIZE);
51+
return (long) SIZE_HANDLE.get(struct, 0L);
3852
}
3953

4054
long pos() {
41-
return struct.get(JAVA_LONG, OFF_POS);
55+
return (long) POS_HANDLE.get(struct, 0L);
4256
}
4357
}

0 commit comments

Comments
 (0)