Skip to content

Commit 0fcb9b3

Browse files
dfa1claude
andcommitted
build: enforce zero warnings (javac -Xlint:all, javadoc failOnWarnings)
- compiler: -Xlint:all + failOnWarning, so any javac lint fails the build - javadoc: failOnError + failOnWarnings, bound to the verify phase - fixes surfaced by the policy: - ZstdException gets a serialVersionUID - @SuppressWarnings("restricted") on the FFM call sites (libraryLookup, downcallHandle, reinterpret) — intrinsic to FFM, acknowledged explicitly - complete @param/@return/@throws on all public + protected members verify green, 40 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 5512e70 commit 0fcb9b3

10 files changed

Lines changed: 117 additions & 0 deletions

File tree

pom.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,21 @@
102102
<version>3.15.0</version>
103103
<configuration>
104104
<release>25</release>
105+
<failOnWarning>true</failOnWarning>
106+
<compilerArgs>
107+
<arg>-Xlint:all</arg>
108+
</compilerArgs>
109+
</configuration>
110+
</plugin>
111+
<plugin>
112+
<groupId>org.apache.maven.plugins</groupId>
113+
<artifactId>maven-javadoc-plugin</artifactId>
114+
<version>3.12.0</version>
115+
<configuration>
116+
<release>25</release>
117+
<failOnError>true</failOnError>
118+
<failOnWarnings>true</failOnWarnings>
119+
<quiet>true</quiet>
105120
</configuration>
106121
</plugin>
107122
<plugin>
@@ -154,6 +169,19 @@
154169
<groupId>org.apache.maven.plugins</groupId>
155170
<artifactId>maven-checkstyle-plugin</artifactId>
156171
</plugin>
172+
<plugin>
173+
<groupId>org.apache.maven.plugins</groupId>
174+
<artifactId>maven-javadoc-plugin</artifactId>
175+
<executions>
176+
<execution>
177+
<id>javadoc-no-warnings</id>
178+
<phase>verify</phase>
179+
<goals>
180+
<goal>javadoc</goal>
181+
</goals>
182+
</execution>
183+
</executions>
184+
</plugin>
157185
</plugins>
158186
</build>
159187
</project>

zstd/src/main/java/io/github/dfa1/zstdffm/NativeLibrary.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
/// The library is resolved from the platform-specific native JAR on the
1818
/// classpath, extracted to a temp file, and loaded once at class-init time.
1919
/// Override with `-Dzstd.lib.path=/path/to/libzstd.so`.
20+
@SuppressWarnings("restricted") // libraryLookup / downcallHandle are restricted FFM methods
2021
final class NativeLibrary {
2122

2223
private static final Linker LINKER = Linker.nativeLinker();

zstd/src/main/java/io/github/dfa1/zstdffm/NativeObject.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ public abstract class NativeObject implements AutoCloseable {
1212

1313
private final AtomicReference<MemorySegment> ptr;
1414

15+
/// Takes ownership of a freshly created native pointer.
16+
///
17+
/// @param owningPointer the non-NULL native pointer this object now owns
1518
protected NativeObject(MemorySegment owningPointer) {
1619
this.ptr = new AtomicReference<>(owningPointer);
1720
}
1821

22+
/// Returns the live native pointer, failing if this object is already closed.
23+
///
1924
/// @return the live native pointer
2025
/// @throws IllegalStateException if this object has been closed
2126
protected final MemorySegment ptr() {
@@ -39,5 +44,8 @@ public final void close() {
3944
}
4045

4146
/// Releases the native resource. Called exactly once with a non-NULL pointer.
47+
///
48+
/// @param ptr the non-NULL native pointer to free
49+
/// @throws Throwable if the native free call fails; the exception is swallowed by {@link #close()}
4250
protected abstract void tryClose(MemorySegment ptr) throws Throwable;
4351
}

zstd/src/main/java/io/github/dfa1/zstdffm/Zstd.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ public static long decompressedSize(MemorySegment frame) {
108108

109109
/// Maximum compressed size for an input of `srcSize` bytes — the buffer
110110
/// size guaranteed to never overflow during compression.
111+
///
112+
/// @param srcSize the uncompressed input length in bytes
113+
/// @return the worst-case compressed size for that input
111114
public static long compressBound(long srcSize) {
112115
try {
113116
return (long) Bindings.COMPRESS_BOUND.invokeExact(srcSize);
@@ -127,6 +130,8 @@ private static long frameContentSize(byte[] compressed) {
127130
}
128131

129132
/// Highest supported compression level.
133+
///
134+
/// @return the maximum valid compression level
130135
public static int maxCompressionLevel() {
131136
try {
132137
return (int) Bindings.MAX_C_LEVEL.invokeExact();
@@ -136,6 +141,8 @@ public static int maxCompressionLevel() {
136141
}
137142

138143
/// Lowest supported compression level (negative levels trade ratio for speed).
144+
///
145+
/// @return the minimum valid compression level
139146
public static int minCompressionLevel() {
140147
try {
141148
return (int) Bindings.MIN_C_LEVEL.invokeExact();
@@ -145,6 +152,8 @@ public static int minCompressionLevel() {
145152
}
146153

147154
/// The level used by {@link #compress(byte[])}.
155+
///
156+
/// @return the default compression level
148157
public static int defaultCompressionLevel() {
149158
try {
150159
return (int) Bindings.DEFAULT_C_LEVEL.invokeExact();
@@ -154,6 +163,9 @@ public static int defaultCompressionLevel() {
154163
}
155164

156165
/// Runtime zstd version, e.g. `"1.6.0"`.
166+
///
167+
/// @return the linked zstd library version as an `x.y.z` string
168+
@SuppressWarnings("restricted") // reinterpret needed to read a C string of unknown length
157169
public static String version() {
158170
try {
159171
MemorySegment p = (MemorySegment) Bindings.VERSION_STRING.invokeExact();
@@ -194,6 +206,7 @@ private static boolean isError(long code) {
194206
}
195207
}
196208

209+
@SuppressWarnings("restricted") // reinterpret needed to read a C string of unknown length
197210
private static String errorName(long code) {
198211
try {
199212
MemorySegment p = (MemorySegment) Bindings.GET_ERROR_NAME.invokeExact(code);

zstd/src/main/java/io/github/dfa1/zstdffm/ZstdCompressCtx.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public final class ZstdCompressCtx extends NativeObject {
2020

2121
private int level = Zstd.defaultCompressionLevel();
2222

23+
/// Creates a new compression context at the default level.
2324
public ZstdCompressCtx() {
2425
super(create());
2526
}
@@ -38,13 +39,17 @@ private static MemorySegment create() {
3839

3940
/// Sets the compression level for subsequent {@link #compress} calls.
4041
///
42+
/// @param level the compression level to use
4143
/// @return `this`, for chaining
4244
public ZstdCompressCtx level(int level) {
4345
this.level = level;
4446
return this;
4547
}
4648

4749
/// Compresses `src` into a new zstd frame using this context.
50+
///
51+
/// @param src the bytes to compress
52+
/// @return a self-describing zstd frame
4853
public byte[] compress(byte[] src) {
4954
try (Arena arena = Arena.ofConfined()) {
5055
MemorySegment in = Zstd.copyIn(arena, src);
@@ -61,6 +66,10 @@ public byte[] compress(byte[] src) {
6166
/// The dictionary is re-digested on every call; for repeated compression
6267
/// against the same dictionary, digest it once into a {@link ZstdCompressDict}
6368
/// and use {@link #compress(byte[], ZstdCompressDict)}.
69+
///
70+
/// @param src the bytes to compress
71+
/// @param dict the dictionary to compress against
72+
/// @return a self-describing zstd frame
6473
public byte[] compress(byte[] src, ZstdDictionary dict) {
6574
try (Arena arena = Arena.ofConfined()) {
6675
MemorySegment in = Zstd.copyIn(arena, src);
@@ -76,6 +85,10 @@ public byte[] compress(byte[] src, ZstdDictionary dict) {
7685

7786
/// Compresses `src` against a pre-digested `dict` (the level was
7887
/// fixed when the {@link ZstdCompressDict} was built).
88+
///
89+
/// @param src the bytes to compress
90+
/// @param dict the pre-digested compression dictionary
91+
/// @return a self-describing zstd frame
7992
public byte[] compress(byte[] src, ZstdCompressDict dict) {
8093
try (Arena arena = Arena.ofConfined()) {
8194
MemorySegment in = Zstd.copyIn(arena, src);
@@ -96,6 +109,8 @@ public byte[] compress(byte[] src, ZstdCompressDict dict) {
96109
///
97110
/// Size `dst` with {@link Zstd#compressBound(long)} to guarantee it fits.
98111
///
112+
/// @param dst the native destination buffer to write the frame into
113+
/// @param src the native source bytes to compress
99114
/// @return the number of bytes written into `dst`
100115
/// @throws ZstdException if `dst` is too small or compression fails
101116
public long compress(MemorySegment dst, MemorySegment src) {
@@ -105,6 +120,9 @@ public long compress(MemorySegment dst, MemorySegment src) {
105120

106121
/// Zero-copy compression against a pre-digested `dict`, segment to segment.
107122
///
123+
/// @param dst the native destination buffer to write the frame into
124+
/// @param src the native source bytes to compress
125+
/// @param dict the pre-digested compression dictionary
108126
/// @return the number of bytes written into `dst`
109127
public long compress(MemorySegment dst, MemorySegment src, ZstdCompressDict dict) {
110128
MemorySegment cdict = dict.ptr();
@@ -117,6 +135,8 @@ public long compress(MemorySegment dst, MemorySegment src, ZstdCompressDict dict
117135
/// compresses into it, and returns a slice trimmed to the actual frame length.
118136
/// The returned segment is owned by `arena`.
119137
///
138+
/// @param arena the arena to allocate the output segment in
139+
/// @param src the native source bytes to compress
120140
/// @return the zstd frame, a slice of an `arena`-owned segment
121141
public MemorySegment compress(Arena arena, MemorySegment src) {
122142
MemorySegment dst = arena.allocate(Zstd.compressBound(src.byteSize()));
@@ -127,6 +147,9 @@ public MemorySegment compress(Arena arena, MemorySegment src) {
127147
/// Zero-copy compression against a pre-digested `dict`, allocating the
128148
/// output in `arena` and returning a slice trimmed to the frame length.
129149
///
150+
/// @param arena the arena to allocate the output segment in
151+
/// @param src the native source bytes to compress
152+
/// @param dict the pre-digested compression dictionary
130153
/// @return the zstd frame, a slice of an `arena`-owned segment
131154
public MemorySegment compress(Arena arena, MemorySegment src, ZstdCompressDict dict) {
132155
MemorySegment dst = arena.allocate(Zstd.compressBound(src.byteSize()));

zstd/src/main/java/io/github/dfa1/zstdffm/ZstdCompressDict.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ public final class ZstdCompressDict extends NativeObject {
1515
private final int level;
1616

1717
/// Digests `dict` for compression at the given level.
18+
///
19+
/// @param dict the dictionary to digest
20+
/// @param level the compression level to fix for this digested dictionary
1821
public ZstdCompressDict(ZstdDictionary dict, int level) {
1922
super(create(dict, level));
2023
this.level = level;
2124
}
2225

2326
/// Digests `dict` for compression at the library default level.
27+
///
28+
/// @param dict the dictionary to digest
2429
public ZstdCompressDict(ZstdDictionary dict) {
2530
this(dict, Zstd.defaultCompressionLevel());
2631
}
@@ -40,6 +45,8 @@ private static MemorySegment create(ZstdDictionary dict, int level) {
4045
}
4146

4247
/// The level this dictionary was digested at.
48+
///
49+
/// @return the fixed compression level
4350
public int level() {
4451
return level;
4552
}

zstd/src/main/java/io/github/dfa1/zstdffm/ZstdDecompressCtx.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/// state allocation. Not thread-safe: confine an instance to one thread or pool it.
1010
public final class ZstdDecompressCtx extends NativeObject {
1111

12+
/// Creates a new decompression context.
1213
public ZstdDecompressCtx() {
1314
super(create());
1415
}
@@ -26,6 +27,10 @@ private static MemorySegment create() {
2627
}
2728

2829
/// Decompresses a frame into a buffer of at most `maxSize` bytes.
30+
///
31+
/// @param compressed a complete zstd frame
32+
/// @param maxSize upper bound on the decompressed length
33+
/// @return the original bytes
2934
public byte[] decompress(byte[] compressed, int maxSize) {
3035
try (Arena arena = Arena.ofConfined()) {
3136
MemorySegment in = Zstd.copyIn(arena, compressed);
@@ -41,6 +46,11 @@ public byte[] decompress(byte[] compressed, int maxSize) {
4146
/// The dictionary is re-digested on every call; for repeated use digest it
4247
/// once into a {@link ZstdDecompressDict} and use
4348
/// {@link #decompress(byte[], int, ZstdDecompressDict)}.
49+
///
50+
/// @param compressed a complete zstd frame
51+
/// @param maxSize upper bound on the decompressed length
52+
/// @param dict the dictionary the frame was compressed against
53+
/// @return the original bytes
4454
public byte[] decompress(byte[] compressed, int maxSize, ZstdDictionary dict) {
4555
try (Arena arena = Arena.ofConfined()) {
4656
MemorySegment in = Zstd.copyIn(arena, compressed);
@@ -54,6 +64,11 @@ public byte[] decompress(byte[] compressed, int maxSize, ZstdDictionary dict) {
5464
}
5565

5666
/// Decompresses a frame against a pre-digested `dict`.
67+
///
68+
/// @param compressed a complete zstd frame
69+
/// @param maxSize upper bound on the decompressed length
70+
/// @param dict the pre-digested decompression dictionary
71+
/// @return the original bytes
5772
public byte[] decompress(byte[] compressed, int maxSize, ZstdDecompressDict dict) {
5873
try (Arena arena = Arena.ofConfined()) {
5974
MemorySegment in = Zstd.copyIn(arena, compressed);
@@ -75,6 +90,8 @@ public byte[] decompress(byte[] compressed, int maxSize, ZstdDecompressDict dict
7590
/// Size `dst` to the decompressed length (read it from the frame with
7691
/// {@link Zstd#decompress(byte[])}'s header logic, or known out-of-band).
7792
///
93+
/// @param dst the native destination buffer to write the result into
94+
/// @param src the native source frame to decompress
7895
/// @return the number of bytes written into `dst`
7996
/// @throws ZstdException if `dst` is too small or the frame is invalid
8097
public long decompress(MemorySegment dst, MemorySegment src) {
@@ -84,6 +101,9 @@ public long decompress(MemorySegment dst, MemorySegment src) {
84101

85102
/// Zero-copy decompression against a pre-digested `dict`, segment to segment.
86103
///
104+
/// @param dst the native destination buffer to write the result into
105+
/// @param src the native source frame to decompress
106+
/// @param dict the pre-digested decompression dictionary
87107
/// @return the number of bytes written into `dst`
88108
public long decompress(MemorySegment dst, MemorySegment src, ZstdDecompressDict dict) {
89109
MemorySegment ddict = dict.ptr();
@@ -100,6 +120,8 @@ public long decompress(MemorySegment dst, MemorySegment src, ZstdDecompressDict
100120
/// library do); for size-less frames use {@link #decompress(MemorySegment, MemorySegment)}
101121
/// with a destination you size yourself.
102122
///
123+
/// @param arena the arena to allocate the output segment in
124+
/// @param frame a complete zstd frame storing its decompressed size
103125
/// @return a segment of exactly the decompressed length, allocated in `arena`
104126
/// @throws ZstdException if the frame is invalid or stores no size
105127
public MemorySegment decompress(Arena arena, MemorySegment frame) {
@@ -112,6 +134,9 @@ public MemorySegment decompress(Arena arena, MemorySegment frame) {
112134
/// Zero-copy decompression against a pre-digested `dict`, allocating the
113135
/// exact-sized output in `arena`.
114136
///
137+
/// @param arena the arena to allocate the output segment in
138+
/// @param frame a complete zstd frame storing its decompressed size
139+
/// @param dict the pre-digested decompression dictionary
115140
/// @return a segment of exactly the decompressed length, allocated in `arena`
116141
public MemorySegment decompress(Arena arena, MemorySegment frame, ZstdDecompressDict dict) {
117142
long size = Zstd.decompressedSize(frame);

zstd/src/main/java/io/github/dfa1/zstdffm/ZstdDecompressDict.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
public final class ZstdDecompressDict extends NativeObject {
1313

1414
/// Digests `dict` for decompression.
15+
///
16+
/// @param dict the dictionary to digest
1517
public ZstdDecompressDict(ZstdDictionary dict) {
1618
super(create(dict));
1719
}

zstd/src/main/java/io/github/dfa1/zstdffm/ZstdDictionary.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ private ZstdDictionary(byte[] bytes) {
3636
/// dictionary shipped with your application).
3737
///
3838
/// @param raw dictionary bytes; defensively copied
39+
/// @return a dictionary wrapping a copy of `raw`
3940
public static ZstdDictionary of(byte[] raw) {
4041
return new ZstdDictionary(raw.clone());
4142
}
@@ -87,6 +88,8 @@ public static ZstdDictionary train(List<byte[]> samples, int maxDictBytes) {
8788

8889
/// The dictionary id zstd stamps into frames compressed with this dictionary,
8990
/// or `0` for a raw/content-only dictionary with no header.
91+
///
92+
/// @return the dictionary id, or `0` if none
9093
public int id() {
9194
try (Arena arena = Arena.ofConfined()) {
9295
MemorySegment seg = Zstd.copyIn(arena, bytes);
@@ -96,11 +99,15 @@ public int id() {
9699
}
97100
}
98101

102+
/// Serialises this dictionary to a fresh byte array.
103+
///
99104
/// @return a copy of the raw dictionary bytes, suitable for persisting
100105
public byte[] toByteArray() {
101106
return bytes.clone();
102107
}
103108

109+
/// The size of this dictionary.
110+
///
104111
/// @return the dictionary size in bytes
105112
public int size() {
106113
return bytes.length;
@@ -119,6 +126,7 @@ private static boolean zdictIsError(long code) {
119126
}
120127
}
121128

129+
@SuppressWarnings("restricted") // reinterpret needed to read a C string of unknown length
122130
private static String zdictErrorName(long code) {
123131
try {
124132
MemorySegment p = (MemorySegment) Bindings.ZDICT_GET_ERROR_NAME.invokeExact(code);

zstd/src/main/java/io/github/dfa1/zstdffm/ZstdException.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
/// recoverable I/O condition.
88
public final class ZstdException extends RuntimeException {
99

10+
private static final long serialVersionUID = 1L;
11+
1012
ZstdException(String message) {
1113
super(message);
1214
}

0 commit comments

Comments
 (0)