Kill the naked int: ZstdCompressionLevel value type#97
Conversation
|
|
||
| /// Validates `value` against the linked libzstd's accepted range. | ||
| public ZstdCompressionLevel { | ||
| int min = Zstd.minCompressionLevel(); |
There was a problem hiding this comment.
so let's hide the public constructor
|
Re: hiding the public constructor — Java won't let us. A record's canonical constructor can't be more restrictive than the record type itself, and So The alternative would be dropping the record for a hand-written final class with a private constructor + manual |
|
Dropped |
| /// Validates `value` against the linked libzstd's accepted range. | ||
| public ZstdCompressionLevel { | ||
| int min = Zstd.minCompressionLevel(); | ||
| int max = Zstd.maxCompressionLevel(); |
There was a problem hiding this comment.
also, would it be possible to cache these 2 values? otherwise every new level will leads to 2 native calls... is that necessary for some reason?
| } | ||
|
|
||
| private static ZstdDictionary optimize(List<byte[]> samples, int maxDictBytes, | ||
| int compressionLevel, boolean fast) { |
There was a problem hiding this comment.
why do we need fast as boolean? I guess we could derive it from the CompressionLevel no?
|
Re: caching min/max — good catch, no reason not to. Cached both in |
|
Re: the |
Introduces ZstdCompressionLevel, a record wrapping the compression level as a validated int, checked in its compact constructor against Zstd.minCompressionLevel()/maxCompressionLevel() (IllegalArgumentException if out of range) rather than deferring to native clamping/errors. The accepted range is queried from libzstd once and cached, since it never changes for the life of the process. Ships DEFAULT/FASTEST/MAX constants for the common cases; construct directly (new ZstdCompressionLevel(n)) for any other level — there is no separate of(int) factory, since a public record's canonical constructor can't be hidden anyway. Replaces every naked int level parameter with it across Zstd, ZstdCompressContext, ZstdCompressStream, ZstdCompressDictionary, ZstdDictionary, and ZstdOutputStream. Zstd.min/max/defaultCompressionLevel() keep returning int, since they're the bound queries the new type validates against. Breaking change; the library is pre-1.0 so no compatibility shims are added. Closes #93.
bcd841a to
9a72557
Compare
Summary
ZstdCompressionLevel, a record wrapping the compression level as a validatedint— the compact constructor checks it againstZstd.minCompressionLevel()/maxCompressionLevel()and throwsIllegalArgumentExceptionout of range, instead of deferring to native clamping/errors. ShipsDEFAULT/FASTEST/MAXconstants and anof(int)factory.int levelparameter across the public API with it:Zstd.compress,Zstd.estimateCompressContextSize/estimateCompressDictSize,ZstdCompressContext.level,ZstdCompressStream,ZstdOutputStream,ZstdCompressDictionary,ZstdDictionary.compressDict/trainCover/trainFastCover/finalizeFrom.Zstd.min/max/defaultCompressionLevel()deliberately keep returning rawint— they're the bound queriesZstdCompressionLevel's own constructor validates against.[Unreleased].Closes #93.
Filed #96 as a separate follow-up for a possibly analogous "size" value type (
maxDictBytes/dictSize/pledgedSrcSize/maxSize) — kept out of this PR's scope on purpose.Test plan
./mvnw -pl zstd,integration-tests,benchmark -am clean verify— build success, 284 unit + 85 integration tests, 0 failures./mvnw -pl zstd validate— checkstyle clean./mvnw -pl zstd javadoc:javadoc— zero output (failOnError/failOnWarnings)ZstdCompressionLevelTestcovering valid construction,of(), theDEFAULT/FASTEST/MAXconstants against the library bounds, andIllegalArgumentExceptionat one-below-min/one-above-max.value()extraction correctness at every native-call boundary, the ZDICT0-default sentinel, and stale test assertions — no issues found🤖 Generated with Claude Code