diff --git a/.gitignore b/.gitignore index 03ecbde6af8..ca36eb38e1f 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,10 @@ build-* cmakebuild/ cmake-build/ +# Swift build artefacts +.build/ +.swiftpm/xcode/ + # Test artefacts tmp* *.zst diff --git a/Package.swift b/Package.swift index 97f2c6a5251..cf33c6f5240 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.0 +// swift-tools-version:5.5 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -6,29 +6,66 @@ import PackageDescription let package = Package( name: "zstd", platforms: [ - .macOS(.v10_10), .iOS(.v9), .tvOS(.v9) + .macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6) ], products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. - .library( - name: "libzstd", - targets: [ "libzstd" ]) - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), + // Two library products. Each surfaces only one Swift module to its consumers: + // + // • `Zstd` — modern API (renamed functions, prefix-stripped enum cases). + // • `libzstd` — legacy API (raw `ZSTD_*` names) for source-level backwards + // compatibility with code that predates the rename. + // + // A consumer that depends on the `Zstd` product can NOT `import libzstd` + // (and vice versa), because each product is backed by a separate facade + // target whose modulemap declares only one of the two modules. + .library(name: "Zstd", targets: [ "Zstd" ]), + .library(name: "libzstd", targets: [ "libzstd" ]), + .executable(name: "zstd-example", targets: [ "zstd-example" ]), ], targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. + // ── The actual C library ──────────────────────────────────────────── + // Compiles the real zstd sources once and exposes the raw headers via + // a "private" `_ZstdCore` module that nobody is expected to import. + // Both facade targets below depend on this one for the C symbols. .target( - name: "libzstd", + name: "_ZstdCore", path: "lib", sources: [ "common", "compress", "decompress", "dictBuilder" ], publicHeadersPath: ".", cSettings: [ - .headerSearchPath(".") - ]) + .headerSearchPath("."), + ]), + + // ── Modern Swift facade ───────────────────────────────────────────── + // Owns the `Zstd_module.h` umbrella (which defines + // `ZSTD_FOR_SWIFT_MODERN_API` before including the real headers) and + // its accompanying `Zstd.apinotes`. The umbrella + apinotes pair is the + // only thing that turns "raw zstd headers" into the modern Swift API. + .target( + name: "Zstd", + dependencies: [ "_ZstdCore" ], + path: "Sources/Zstd", + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("../../lib"), // so the umbrella can find zstd.h + ]), + + // ── Legacy Swift facade ───────────────────────────────────────────── + // Same headers as `Zstd`, but with an umbrella that doesn't define the + // modern-API macro and no apinotes file, so the raw C names come through. + .target( + name: "libzstd", + dependencies: [ "_ZstdCore" ], + path: "Sources/libzstd", + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("../../lib"), + ]), + + .executableTarget( + name: "zstd-example", + dependencies: [ "Zstd" ], + path: "Sources/zstd-example"), ], swiftLanguageVersions: [.v5], cLanguageStandard: .gnu11, diff --git a/Sources/Zstd/_empty.c b/Sources/Zstd/_empty.c new file mode 100644 index 00000000000..8a4dfb92063 --- /dev/null +++ b/Sources/Zstd/_empty.c @@ -0,0 +1 @@ +// SwiftPM requires at least one source file per C target. diff --git a/Sources/Zstd/include/Zstd.apinotes b/Sources/Zstd/include/Zstd.apinotes new file mode 100644 index 00000000000..caf856fbd40 --- /dev/null +++ b/Sources/Zstd/include/Zstd.apinotes @@ -0,0 +1,389 @@ +--- +Name: Zstd + +# ─── Type renames ──────────────────────────────────────────────────────────── +# C struct tags (the underlying `_s` suffixed names) and their corresponding +# typedef aliases both need an entry — the Swift importer surfaces both. +Tags: + - Name: ZSTD_inBuffer_s + SwiftName: 'InputBuffer' + - Name: ZSTD_outBuffer_s + SwiftName: 'OutputBuffer' + - Name: ZSTD_bounds + SwiftName: 'ParameterBounds' + +Typedefs: + - Name: ZSTD_inBuffer + SwiftName: 'InputBuffer' + - Name: ZSTD_outBuffer + SwiftName: 'OutputBuffer' + - Name: ZSTD_bounds + SwiftName: 'ParameterBounds' + - Name: ZDICT_params_t + SwiftName: 'DictionaryTrainingParameters' + - Name: ZSTD_strategy + SwiftName: 'Strategy' + - Name: ZSTD_cParameter + SwiftName: 'CompressionParameter' + - Name: ZSTD_dParameter + SwiftName: 'DecompressionParameter' + - Name: ZSTD_ResetDirective + SwiftName: 'ResetDirective' + - Name: ZSTD_EndDirective + SwiftName: 'EndDirective' + - Name: ZSTD_ErrorCode + SwiftName: 'ErrorCode' + +# ─── Enum case renames ─────────────────────────────────────────────────────── +# The clang importer's automatic prefix-stripping only removes `ZSTD_` here — +# it stops at the type-name-shared boundary and won't strip a further `e_`, +# `reset_`, or `error_` sub-prefix. We rename the cases explicitly. +Enumerators: + # CompressionParameter — expand the few remaining abbreviations. + - Name: ZSTD_c_targetCBlockSize + SwiftName: 'targetCompressedBlockSize' + - Name: ZSTD_c_nbWorkers + SwiftName: 'workerCount' + - Name: ZSTD_c_contentSizeFlag + SwiftName: 'embedContentSize' + - Name: ZSTD_c_checksumFlag + SwiftName: 'embedChecksum' + - Name: ZSTD_c_dictIDFlag + SwiftName: 'embedDictionaryID' + - Name: ZSTD_c_experimentalParam1 + SwiftName: 'experimentalParameter1' + - Name: ZSTD_c_experimentalParam2 + SwiftName: 'experimentalParameter2' + - Name: ZSTD_c_experimentalParam3 + SwiftName: 'experimentalParameter3' + - Name: ZSTD_c_experimentalParam4 + SwiftName: 'experimentalParameter4' + - Name: ZSTD_c_experimentalParam5 + SwiftName: 'experimentalParameter5' + - Name: ZSTD_c_experimentalParam7 + SwiftName: 'experimentalParameter7' + - Name: ZSTD_c_experimentalParam8 + SwiftName: 'experimentalParameter8' + - Name: ZSTD_c_experimentalParam9 + SwiftName: 'experimentalParameter9' + - Name: ZSTD_c_experimentalParam10 + SwiftName: 'experimentalParameter10' + - Name: ZSTD_c_experimentalParam11 + SwiftName: 'experimentalParameter11' + - Name: ZSTD_c_experimentalParam12 + SwiftName: 'experimentalParameter12' + - Name: ZSTD_c_experimentalParam13 + SwiftName: 'experimentalParameter13' + - Name: ZSTD_c_experimentalParam14 + SwiftName: 'experimentalParameter14' + - Name: ZSTD_c_experimentalParam15 + SwiftName: 'experimentalParameter15' + - Name: ZSTD_c_experimentalParam16 + SwiftName: 'experimentalParameter16' + - Name: ZSTD_c_experimentalParam17 + SwiftName: 'experimentalParameter17' + - Name: ZSTD_c_experimentalParam18 + SwiftName: 'experimentalParameter18' + - Name: ZSTD_c_experimentalParam19 + SwiftName: 'experimentalParameter19' + - Name: ZSTD_c_experimentalParam20 + SwiftName: 'experimentalParameter20' + + # DecompressionParameter — experimental cases share the `d_experimentalParamN` form. + - Name: ZSTD_d_experimentalParam1 + SwiftName: 'experimentalParameter1' + - Name: ZSTD_d_experimentalParam2 + SwiftName: 'experimentalParameter2' + - Name: ZSTD_d_experimentalParam3 + SwiftName: 'experimentalParameter3' + - Name: ZSTD_d_experimentalParam4 + SwiftName: 'experimentalParameter4' + - Name: ZSTD_d_experimentalParam5 + SwiftName: 'experimentalParameter5' + - Name: ZSTD_d_experimentalParam6 + SwiftName: 'experimentalParameter6' + + # EndDirective + - Name: ZSTD_e_continue + SwiftName: 'continue' + - Name: ZSTD_e_flush + SwiftName: 'flush' + - Name: ZSTD_e_end + SwiftName: 'end' + + # ResetDirective + - Name: ZSTD_reset_session_only + SwiftName: 'sessionOnly' + - Name: ZSTD_reset_parameters + SwiftName: 'parameters' + - Name: ZSTD_reset_session_and_parameters + SwiftName: 'sessionAndParameters' + + # ErrorCode + - Name: ZSTD_error_no_error + SwiftName: 'noError' + - Name: ZSTD_error_GENERIC + SwiftName: 'generic' + - Name: ZSTD_error_prefix_unknown + SwiftName: 'prefixUnknown' + - Name: ZSTD_error_version_unsupported + SwiftName: 'versionUnsupported' + - Name: ZSTD_error_frameParameter_unsupported + SwiftName: 'frameParameterUnsupported' + - Name: ZSTD_error_frameParameter_windowTooLarge + SwiftName: 'frameParameterWindowTooLarge' + - Name: ZSTD_error_corruption_detected + SwiftName: 'corruptionDetected' + - Name: ZSTD_error_checksum_wrong + SwiftName: 'checksumWrong' + - Name: ZSTD_error_literals_headerWrong + SwiftName: 'literalsHeaderWrong' + - Name: ZSTD_error_dictionary_corrupted + SwiftName: 'dictionaryCorrupted' + - Name: ZSTD_error_dictionary_wrong + SwiftName: 'dictionaryWrong' + - Name: ZSTD_error_dictionaryCreation_failed + SwiftName: 'dictionaryCreationFailed' + - Name: ZSTD_error_parameter_unsupported + SwiftName: 'parameterUnsupported' + - Name: ZSTD_error_parameter_combination_unsupported + SwiftName: 'parameterCombinationUnsupported' + - Name: ZSTD_error_parameter_outOfBound + SwiftName: 'parameterOutOfBound' + - Name: ZSTD_error_tableLog_tooLarge + SwiftName: 'tableLogTooLarge' + - Name: ZSTD_error_maxSymbolValue_tooLarge + SwiftName: 'maxSymbolValueTooLarge' + - Name: ZSTD_error_maxSymbolValue_tooSmall + SwiftName: 'maxSymbolValueTooSmall' + - Name: ZSTD_error_cannotProduce_uncompressedBlock + SwiftName: 'cannotProduceUncompressedBlock' + - Name: ZSTD_error_stabilityCondition_notRespected + SwiftName: 'stabilityConditionNotRespected' + - Name: ZSTD_error_stage_wrong + SwiftName: 'stageWrong' + - Name: ZSTD_error_init_missing + SwiftName: 'initMissing' + - Name: ZSTD_error_memory_allocation + SwiftName: 'memoryAllocation' + - Name: ZSTD_error_workSpace_tooSmall + SwiftName: 'workSpaceTooSmall' + - Name: ZSTD_error_dstSize_tooSmall + SwiftName: 'destinationSizeTooSmall' + - Name: ZSTD_error_srcSize_wrong + SwiftName: 'sourceSizeWrong' + - Name: ZSTD_error_dstBuffer_null + SwiftName: 'destinationBufferNull' + - Name: ZSTD_error_noForwardProgress_destFull + SwiftName: 'noForwardProgressDestinationFull' + - Name: ZSTD_error_noForwardProgress_inputEmpty + SwiftName: 'noForwardProgressInputEmpty' + - Name: ZSTD_error_frameIndex_tooLarge + SwiftName: 'frameIndexTooLarge' + - Name: ZSTD_error_seekableIO + SwiftName: 'seekableIO' + - Name: ZSTD_error_dstBuffer_wrong + SwiftName: 'destinationBufferWrong' + - Name: ZSTD_error_srcBuffer_wrong + SwiftName: 'sourceBufferWrong' + - Name: ZSTD_error_sequenceProducer_failed + SwiftName: 'sequenceProducerFailed' + - Name: ZSTD_error_externalSequences_invalid + SwiftName: 'externalSequencesInvalid' + - Name: ZSTD_error_maxCode + SwiftName: 'maxCode' + +# ─── Constants (Globals) ───────────────────────────────────────────────────── +# `#define`d constants in the C headers are imported as Swift `let`s. Rename +# them to camelCase without the ZSTD_ prefix. `defaultCompressionLevelValue` +# is named with a `Value` suffix to avoid colliding with the function +# `defaultCompressionLevel()`. +Globals: + - Name: ZSTD_VERSION_MAJOR + SwiftName: 'versionMajor' + - Name: ZSTD_VERSION_MINOR + SwiftName: 'versionMinor' + - Name: ZSTD_VERSION_RELEASE + SwiftName: 'versionRelease' + - Name: ZSTD_MAGICNUMBER + SwiftName: 'magicNumber' + - Name: ZSTD_MAGIC_DICTIONARY + SwiftName: 'magicDictionary' + - Name: ZSTD_MAGIC_SKIPPABLE_START + SwiftName: 'magicSkippableStart' + - Name: ZSTD_MAGIC_SKIPPABLE_MASK + SwiftName: 'magicSkippableMask' + - Name: ZSTD_BLOCKSIZELOG_MAX + SwiftName: 'blockSizeLog2Max' + - Name: ZSTD_BLOCKSIZE_MAX + SwiftName: 'blockSizeMax' + - Name: ZSTD_CLEVEL_DEFAULT + SwiftName: 'defaultCompressionLevelValue' + - Name: ZSTD_CONTENTSIZE_UNKNOWN + SwiftName: 'contentSizeUnknown' + - Name: ZSTD_CONTENTSIZE_ERROR + SwiftName: 'contentSizeError' + +# ─── Functions ─────────────────────────────────────────────────────────────── +Functions: + - Name: ZSTD_versionNumber + SwiftName: 'versionNumber()' + - Name: ZSTD_versionString + SwiftName: 'versionString()' + - Name: ZSTD_compress + SwiftName: 'compress(into:capacity:from:size:level:)' + - Name: ZSTD_decompress + SwiftName: 'decompress(into:capacity:from:size:)' + - Name: ZSTD_getFrameContentSize + SwiftName: 'frameContentSize(of:size:)' + - Name: ZSTD_getDecompressedSize + SwiftName: 'decompressedSize(of:size:)' + - Name: ZSTD_findFrameCompressedSize + SwiftName: 'frameCompressedSize(of:size:)' + - Name: ZSTD_compressBound + SwiftName: 'compressionBound(_:)' + - Name: ZSTD_isError + SwiftName: 'isError(_:)' + - Name: ZSTD_getErrorCode + SwiftName: 'errorCode(_:)' + - Name: ZSTD_getErrorName + SwiftName: 'errorName(_:)' + - Name: ZSTD_minCLevel + SwiftName: 'minimumCompressionLevel()' + - Name: ZSTD_maxCLevel + SwiftName: 'maximumCompressionLevel()' + - Name: ZSTD_defaultCLevel + SwiftName: 'defaultCompressionLevel()' + - Name: ZSTD_createCCtx + SwiftName: 'createCompressionContext()' + - Name: ZSTD_freeCCtx + SwiftName: 'freeCompressionContext(_:)' + - Name: ZSTD_compressCCtx + SwiftName: 'compress(_:into:capacity:from:size:level:)' + - Name: ZSTD_createDCtx + SwiftName: 'createDecompressionContext()' + - Name: ZSTD_freeDCtx + SwiftName: 'freeDecompressionContext(_:)' + - Name: ZSTD_decompressDCtx + SwiftName: 'decompress(_:into:capacity:from:size:)' + - Name: ZSTD_cParam_getBounds + SwiftName: 'compressionParameterBounds(_:)' + - Name: ZSTD_CCtx_setParameter + SwiftName: 'setCompressionParameter(_:_:to:)' + - Name: ZSTD_CCtx_setPledgedSrcSize + SwiftName: 'setPledgedCompressionSourceSize(_:to:)' + - Name: ZSTD_CCtx_reset + SwiftName: 'resetCompressionContext(_:directive:)' + - Name: ZSTD_compress2 + SwiftName: 'compress(_:into:capacity:from:size:)' + - Name: ZSTD_dParam_getBounds + SwiftName: 'decompressionParameterBounds(_:)' + - Name: ZSTD_DCtx_setParameter + SwiftName: 'setDecompressionParameter(_:_:to:)' + # Bool-typed convenience overloads (wrappers live in Zstd_module.h). + # Same Swift name as the int-typed setters above — Swift dispatches + # to whichever overload matches the literal's type at the call site. + - Name: Zstd_setCompressionFlag + SwiftName: 'setCompressionParameter(_:_:to:)' + - Name: Zstd_setDecompressionFlag + SwiftName: 'setDecompressionParameter(_:_:to:)' + - Name: ZSTD_DCtx_reset + SwiftName: 'resetDecompressionContext(_:directive:)' + - Name: ZSTD_createCStream + SwiftName: 'createCompressionStream()' + - Name: ZSTD_freeCStream + SwiftName: 'freeCompressionStream(_:)' + - Name: ZSTD_compressStream2 + SwiftName: 'compressStream(_:output:input:directive:)' + - Name: ZSTD_CStreamInSize + SwiftName: 'compressionStreamInputSize()' + - Name: ZSTD_CStreamOutSize + SwiftName: 'compressionStreamOutputSize()' + - Name: ZSTD_initCStream + SwiftName: 'initializeCompressionStream(_:level:)' + - Name: ZSTD_compressStream + SwiftName: 'compressStream(_:output:input:)' + - Name: ZSTD_flushStream + SwiftName: 'flushStream(_:output:)' + - Name: ZSTD_endStream + SwiftName: 'endStream(_:output:)' + - Name: ZSTD_createDStream + SwiftName: 'createDecompressionStream()' + - Name: ZSTD_freeDStream + SwiftName: 'freeDecompressionStream(_:)' + - Name: ZSTD_initDStream + SwiftName: 'initializeDecompressionStream(_:)' + - Name: ZSTD_decompressStream + SwiftName: 'decompressStream(_:output:input:)' + - Name: ZSTD_DStreamInSize + SwiftName: 'decompressionStreamInputSize()' + - Name: ZSTD_DStreamOutSize + SwiftName: 'decompressionStreamOutputSize()' + - Name: ZSTD_compress_usingDict + SwiftName: 'compress(_:into:capacity:from:size:dictionary:dictionarySize:level:)' + - Name: ZSTD_decompress_usingDict + SwiftName: 'decompress(_:into:capacity:from:size:dictionary:dictionarySize:)' + - Name: ZSTD_createCDict + SwiftName: 'createCompressionDictionary(from:size:level:)' + - Name: ZSTD_freeCDict + SwiftName: 'freeCompressionDictionary(_:)' + - Name: ZSTD_compress_usingCDict + SwiftName: 'compress(_:into:capacity:from:size:dictionary:)' + - Name: ZSTD_createDDict + SwiftName: 'createDecompressionDictionary(from:size:)' + - Name: ZSTD_freeDDict + SwiftName: 'freeDecompressionDictionary(_:)' + - Name: ZSTD_decompress_usingDDict + SwiftName: 'decompress(_:into:capacity:from:size:dictionary:)' + - Name: ZSTD_getDictID_fromDict + SwiftName: 'dictionaryID(fromDictionary:size:)' + - Name: ZSTD_getDictID_fromCDict + SwiftName: 'dictionaryID(fromCompressionDictionary:)' + - Name: ZSTD_getDictID_fromDDict + SwiftName: 'dictionaryID(fromDecompressionDictionary:)' + - Name: ZSTD_getDictID_fromFrame + SwiftName: 'dictionaryID(fromFrame:size:)' + - Name: ZSTD_CCtx_loadDictionary + SwiftName: 'loadCompressionDictionary(_:from:size:)' + - Name: ZSTD_CCtx_refCDict + SwiftName: 'attachCompressionDictionary(_:_:)' + - Name: ZSTD_CCtx_refPrefix + SwiftName: 'attachCompressionPrefix(_:from:size:)' + - Name: ZSTD_DCtx_loadDictionary + SwiftName: 'loadDecompressionDictionary(_:from:size:)' + - Name: ZSTD_DCtx_refDDict + SwiftName: 'attachDecompressionDictionary(_:_:)' + - Name: ZSTD_DCtx_refPrefix + SwiftName: 'attachDecompressionPrefix(_:from:size:)' + - Name: ZSTD_sizeof_CCtx + SwiftName: 'memoryUsage(ofCompressionContext:)' + - Name: ZSTD_sizeof_DCtx + SwiftName: 'memoryUsage(ofDecompressionContext:)' + - Name: ZSTD_sizeof_CStream + SwiftName: 'memoryUsage(ofCompressionStream:)' + - Name: ZSTD_sizeof_DStream + SwiftName: 'memoryUsage(ofDecompressionStream:)' + - Name: ZSTD_sizeof_CDict + SwiftName: 'memoryUsage(ofCompressionDictionary:)' + - Name: ZSTD_sizeof_DDict + SwiftName: 'memoryUsage(ofDecompressionDictionary:)' + - Name: ZSTD_getErrorString + SwiftName: 'errorString(_:)' + + # ─── ZDICT_* — dictionary builder ───────────────────────────────────────── + # `dictionaryID(fromTrainedDictionary:size:)` is the ZDICT counterpart of + # `dictionaryID(fromDictionary:size:)` (which lives in the main zstd lib); + # both extract a dictID from a raw buffer, but the distinguishing label + # makes the call-site source-of-truth obvious. + - Name: ZDICT_trainFromBuffer + SwiftName: 'trainDictionary(into:capacity:fromSamples:sampleSizes:sampleCount:)' + - Name: ZDICT_finalizeDictionary + SwiftName: 'finalizeDictionary(into:capacity:from:size:samples:sampleSizes:sampleCount:parameters:)' + - Name: ZDICT_getDictID + SwiftName: 'dictionaryID(fromTrainedDictionary:size:)' + - Name: ZDICT_getDictHeaderSize + SwiftName: 'dictionaryHeaderSize(of:size:)' + - Name: ZDICT_isError + SwiftName: 'isDictionaryError(_:)' + - Name: ZDICT_getErrorName + SwiftName: 'dictionaryErrorName(_:)' diff --git a/Sources/Zstd/include/Zstd_module.h b/Sources/Zstd/include/Zstd_module.h new file mode 100644 index 00000000000..8c463c0a973 --- /dev/null +++ b/Sources/Zstd/include/Zstd_module.h @@ -0,0 +1,96 @@ +/* + * Umbrella header for the modern `Zstd` Swift module. + * + * Setting ZSTD_FOR_SWIFT_MODERN_API enables the in-header annotations + * that benefit the modernised Swift import (e.g. enum_extensibility on + * each ZSTD_xxx enum). The libzstd alias module uses a different umbrella + * (libzstd_module.h) that omits this macro and thus sees raw enums. + * + * The macro is consumed only by zstd.h / zstd_errors.h / zdict.h, which + * declare the relevant enums. + */ + +/* Defined without a value so the Swift importer doesn't see it as a + * top-level `let ZSTD_FOR_SWIFT_MODERN_API: Int32`. `#if defined(...)` + * still works the same. */ +#ifndef ZSTD_FOR_SWIFT_MODERN_API +# define ZSTD_FOR_SWIFT_MODERN_API +#endif + +/* Nullability annotations and assume_nonnull are applied unconditionally + * inside zstd.h / zdict.h (clang's pragma is file-scoped). The legacy + * libzstd umbrella forces ZSTD_NULLABILITY=0 to suppress them and + * preserve its pre-annotation Swift surface. */ +#include "zstd.h" +#include "zdict.h" +#include "zstd_errors.h" + +/* Re-export the `ZSTD_*` / `ZDICT_*` `#define`d constants under nicer Swift + * names. apinotes can rename real declarations (functions, typedefs, tags) + * but not preprocessor macros, so we wrap them as real `static const` + * declarations here. The `#undef`s below then hide the originals from + * Swift's macro importer so each constant only shows up once. */ +static const unsigned versionMajor = ZSTD_VERSION_MAJOR; +static const unsigned versionMinor = ZSTD_VERSION_MINOR; +static const unsigned versionRelease = ZSTD_VERSION_RELEASE; +static const unsigned magicNumber = ZSTD_MAGICNUMBER; +static const unsigned magicDictionary = ZSTD_MAGIC_DICTIONARY; +static const unsigned magicSkippableStart = ZSTD_MAGIC_SKIPPABLE_START; +static const unsigned magicSkippableMask = ZSTD_MAGIC_SKIPPABLE_MASK; +static const int blockSizeMax = ZSTD_BLOCKSIZE_MAX; +static const int blockSizeLog2Max = ZSTD_BLOCKSIZELOG_MAX; +static const int defaultCompressionLevelValue = ZSTD_CLEVEL_DEFAULT; +static const unsigned long long contentSizeUnknown = ZSTD_CONTENTSIZE_UNKNOWN; +static const unsigned long long contentSizeError = ZSTD_CONTENTSIZE_ERROR; + +#undef ZSTD_VERSION_MAJOR +#undef ZSTD_VERSION_MINOR +#undef ZSTD_VERSION_RELEASE +#undef ZSTD_MAGICNUMBER +#undef ZSTD_MAGIC_DICTIONARY +#undef ZSTD_MAGIC_SKIPPABLE_START +#undef ZSTD_MAGIC_SKIPPABLE_MASK +#undef ZSTD_BLOCKSIZE_MAX +#undef ZSTD_BLOCKSIZELOG_MAX +#undef ZSTD_CLEVEL_DEFAULT +#undef ZSTD_CONTENTSIZE_UNKNOWN +#undef ZSTD_CONTENTSIZE_ERROR + +/* Bool-typed overloads of the parameter setters so call sites for the + * flag-style parameters (.embedContentSize, .embedChecksum, + * .embedDictionaryID, .enableLongDistanceMatching, etc.) can pass `true` / + * `false` instead of `1` / `0`. Mapped to the same Swift name as the int-typed + * originals via apinotes; Swift's overload resolution picks the bool variant + * for boolean literals and the int variant for numeric literals. + * + * One caveat to be aware of: nothing at compile time stops one from writing + * setCompressionParameter(cctx, .compressionLevel, to: true). zstd would + * receive 1 and silently set the level to 1. The Swift type system can't tell + * which CompressionParameter cases are boolean-valued and which take an + * integer range, because they're all imported as cases of the same C enum. + * The embed* naming (*Flag in the original C) is the only signal at the call + * site. */ +#include + +#pragma clang assume_nonnull begin + +static inline size_t Zstd_setCompressionFlag(ZSTD_CCtx* cctx, + ZSTD_cParameter param, + bool value) { + return ZSTD_CCtx_setParameter(cctx, param, value ? 1 : 0); +} + +static inline size_t Zstd_setDecompressionFlag(ZSTD_DCtx* dctx, + ZSTD_dParameter param, + bool value) { + return ZSTD_DCtx_setParameter(dctx, param, value ? 1 : 0); +} + +#pragma clang assume_nonnull end + +/* Hide implementation-detail macros from Swift, which would otherwise + * import them as top-level `let` constants (`ZSTD_NULLABILITY`, the + * `` sentinel). The features they control are already in + * scope; the macro values are not part of the API. */ +#undef ZSTD_NULLABILITY +#undef __bool_true_false_are_defined diff --git a/Sources/Zstd/include/module.modulemap b/Sources/Zstd/include/module.modulemap new file mode 100644 index 00000000000..ab44a1501d8 --- /dev/null +++ b/Sources/Zstd/include/module.modulemap @@ -0,0 +1,11 @@ +// Modulemap for the modern Zstd Swift module. +// Includes textual references to the real headers (which live in lib/), +// then the umbrella header sets the ZSTD_FOR_SWIFT_MODERN_API macro +// and `#include`s those headers, picking up the modern annotations. +module Zstd [extern_c] { + header "Zstd_module.h" + textual header "../../../lib/zstd.h" + textual header "../../../lib/zdict.h" + textual header "../../../lib/zstd_errors.h" + export * +} diff --git a/Sources/libzstd/_empty.c b/Sources/libzstd/_empty.c new file mode 100644 index 00000000000..8a4dfb92063 --- /dev/null +++ b/Sources/libzstd/_empty.c @@ -0,0 +1 @@ +// SwiftPM requires at least one source file per C target. diff --git a/Sources/libzstd/include/libzstd_module.h b/Sources/libzstd/include/libzstd_module.h new file mode 100644 index 00000000000..dd90652968d --- /dev/null +++ b/Sources/libzstd/include/libzstd_module.h @@ -0,0 +1,16 @@ +/* + * Umbrella header for the legacy `libzstd` Swift module. + * + * Deliberately does NOT define ZSTD_FOR_SWIFT_MODERN_API so the enums in + * zstd.h import as raw C-style values, preserving the historical Swift + * surface that the libzstd module had before the modernisation. + * + * Also forces ZSTD_NULLABILITY to 0 so the `_Nullable` / `_Nonnull` + * annotations and the `assume_nonnull` pragma added later are not + * applied — pointers continue to import as implicitly-unwrapped + * optionals, matching the original libzstd Swift surface exactly. + */ +#define ZSTD_NULLABILITY 0 +#include "zstd.h" +#include "zdict.h" +#include "zstd_errors.h" diff --git a/Sources/libzstd/include/module.modulemap b/Sources/libzstd/include/module.modulemap new file mode 100644 index 00000000000..e345cfbb6c5 --- /dev/null +++ b/Sources/libzstd/include/module.modulemap @@ -0,0 +1,10 @@ +// Modulemap for the legacy libzstd Swift module. +// Same headers, but the umbrella deliberately omits ZSTD_FOR_SWIFT_MODERN_API, +// so the enums and other annotations stay in their plain-C form. +module libzstd [extern_c] { + header "libzstd_module.h" + textual header "../../../lib/zstd.h" + textual header "../../../lib/zdict.h" + textual header "../../../lib/zstd_errors.h" + export * +} diff --git a/Sources/zstd-example/ZstdExample.swift b/Sources/zstd-example/ZstdExample.swift new file mode 100644 index 00000000000..ef82bbab5cc --- /dev/null +++ b/Sources/zstd-example/ZstdExample.swift @@ -0,0 +1,478 @@ +//===----------------------------------------------------------------------===// +// +// zstd-example +// +// An example use of the Zstd Swift module. +// +// Note: the package ships *two* modules built from the same C headers: +// +// • `import libzstd` — the original raw C API (`ZSTD_createCCtx`, +// `ZSTD_compress`, `ZSTD_CCtx_setParameter`, etc.). Kept for source- +// level backwards compatibility with existing Swift code. +// +// • `import Zstd` — the modern, idiomatic API. It cleans up the names +// so that they are more idiomatic in Swift. e.g. the `ZSTD_` prefix is +// stripped and the `CCtx` / `DCtx` / `CDict` / `DDict` / `Ctx` / +// `Dict` / `Param` / `cLevel` / `Src` abbreviations are expanded +// into full words. +// +// So instead of `ZSTD_createCCtx()` you write +// `createCompressionContext()`; instead of `ZSTD_CCtx_setParameter(...)` +// you write `setCompressionParameter(...)`; `ZSTD_compressBound(...)` +// becomes `compressionBound(...)`; and so on. +// +// Related functions are overloaded by Swift argument labels — +// `compress(…)` covers the simple call, +// `compress(_:into:capacity:from:size:)` is the sticky-parameter form, +// `compress(_:into:capacity:from:size:dictionary:)` uses a precomputed +// dictionary, and so on. Same for `decompress(...)`, +// `compressStream(...)`, `dictionaryID(...)`. +// +// Both modules resolve to the same underlying C library; you can pick +// whichever name you prefer, or even import both. The modern names come +// from an `apinotes` file (`lib/Zstd.apinotes`) that the Swift importer +// applies only to the `Zstd` module. +// +// The renames are purely at compile-time (there are no shims or wrappers +// involved), so the compiled code is identical. +// +// Note: unfortunately, the opaque-context types (CCtx, DCtx, CDict, DDict, +// threadPool, CCtx_params) cannot be imported as Swift classes — their +// structs are forward-declared in the public header, while Swift's +// foreign-reference machinery requires a complete definition. They appear in +// Swift as `OpaquePointer`, and you call free functions on them rather than +// methods. Use `defer { freeCompressionContext(context) }` to ensure +// cleanup. +// +//===----------------------------------------------------------------------===// + +import Foundation +import Zstd + +// MARK: - Sendable pointer wrapper + +// OpaquePointer isn't Sendable in Swift 6. zstd's CDict / DDict are +// documented as safe to share across threads, so we wrap them in an +// `@unchecked Sendable` struct for capture into concurrent tasks. +struct SendableOpaquePointer: @unchecked Sendable { + let pointer: OpaquePointer +} + +// MARK: - Error helpers + +enum ZstdError: Error, CustomStringConvertible { + case operation(_ what: String, code: Int) + case allocationFailed(_ what: String) + + var description: String { + switch self { + case .operation(let what, let code): + return "\(what) failed: \(String(cString: errorName(code)))" + case .allocationFailed(let what): + return "\(what) returned nil — zstd allocation failed" + } + } +} + +@discardableResult +func check(_ result: Int, _ what: String = #function) throws -> Int { + if isError(result) != 0 { + throw ZstdError.operation(what, code: result) + } + return result +} + +// MARK: - Entry point + +@main +struct ZstdExample { + static func main() async throws { + print("libzstd \(String(cString: versionString()))") + print("compression levels: \(minimumCompressionLevel())…\(maximumCompressionLevel()) (default \(defaultCompressionLevel()))") + print(String(repeating: "─", count: 60)) + + let payload = makePayload(repetitions: 2_000) + print("source payload: \(payload.count) bytes\n") + + try oneShotDemo(payload: payload) + try contextDemo(payload: payload) + try streamingDemo(payload: payload) + try await dictionaryDemo() + } + + static func makePayload(repetitions: Int) -> [UInt8] { + let phrase = Array("The quick brown fox jumps over the lazy dog. ".utf8) + var bytes: [UInt8] = [] + bytes.reserveCapacity(phrase.count * repetitions) + for _ in 0.. String { + let r = Double(original) / Double(max(compressed, 1)) + return ratioFormatter.string(from: r as NSNumber) ?? "\(r)x" + } +} + +// MARK: - Demo 1: one-shot compress / decompress + +extension ZstdExample { + /// Demonstrates the simplest possible API: compress and decompress in a single call to a top-level function. + /// + /// With `swift_name` annotations in the header, the C `ZSTD_compress` / `ZSTD_decompress` functions import as `compress(into:capacity:from:size:level:)` and `decompress(into:capacity:from:size:)` — call them directly, or qualify them as `Zstd.compress(…)` / `Zstd.decompress(…)` when the bare name might be ambiguous. + static func oneShotDemo(payload: [UInt8]) throws { + print("# one-shot (top-level functions)") + + let bound = compressionBound(payload.count) + var compressed = [UInt8](repeating: 0, count: bound) + + let compressedSize = try check( + payload.withUnsafeBufferPointer { source in + compressed.withUnsafeMutableBufferPointer { destination in + // Note that the order of arguments is not idiomatic Swift, unfortunately. Re-ordering arguments is not currently supported by Swift's C import machinery (it would require writing wrapper functions explicitly - this is intentionally left as an exercise for 3rd parties, since it introduces more compile-time and run-time complexity than mere symbol renames - e.g. then performance is a potential concern because the wrappers might impose some overhead if not fully inlined). + compress(into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count, + level: 3) + } + }, + "compress" + ) + compressed.removeLast(bound - compressedSize) + + var decompressed = [UInt8](repeating: 0, count: payload.count) + let decompressedSize = try check( + compressed.withUnsafeBufferPointer { source in + decompressed.withUnsafeMutableBufferPointer { destination in + decompress(into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count) + } + }, + "decompress" + ) + + precondition(decompressedSize == payload.count) + precondition(decompressed == payload) + + print(" \(payload.count) → \(compressedSize) bytes (\(ratio(of: payload.count, to: compressedSize)))\n") + } +} + +// MARK: - Demo 2: explicit-context compress / decompress + +extension ZstdExample { + /// Demonstrates the explicit-context API. ZSTD_CCtx and ZSTD_DCtx are opaque pointers (`OpaquePointer`); free functions operate on them. The annotated names drop the `ZSTD_` prefix. + static func contextDemo(payload: [UInt8]) throws { + print("# explicit context (CCtx / DCtx)") + + guard let compressionContext = createCompressionContext() else { + throw ZstdError.allocationFailed("createCompressionContext") + } + defer { _ = freeCompressionContext(compressionContext) } + + // Sticky parameters: persist for every subsequent compression on this context, so a server can configure once and reuse. + try check(setCompressionParameter(compressionContext, .compressionLevel, to: 9)) + try check(setCompressionParameter(compressionContext, .embedChecksum, to: true)) + + let bound = compressionBound(payload.count) + var compressed = [UInt8](repeating: 0, count: bound) + + let compressedSize = try check( + payload.withUnsafeBufferPointer { source in + compressed.withUnsafeMutableBufferPointer { destination in + compress(compressionContext, + into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count) + } + } + ) + compressed.removeLast(bound - compressedSize) + + guard let decompressionContext = createDecompressionContext() else { + throw ZstdError.allocationFailed("createDecompressionContext") + } + defer { _ = freeDecompressionContext(decompressionContext) } + + var decompressed = [UInt8](repeating: 0, count: payload.count) + let decompressedSize = try check( + compressed.withUnsafeBufferPointer { source in + decompressed.withUnsafeMutableBufferPointer { destination in + decompress(decompressionContext, + into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count) + } + } + ) + + precondition(decompressedSize == payload.count) + precondition(decompressed == payload) + + print(" level 9 + checksum: \(payload.count) → \(compressedSize) bytes (\(ratio(of: payload.count, to: compressedSize)))") + print(" CCtx footprint: \(memoryUsage(ofCompressionContext: compressionContext)) bytes") + print(" DCtx footprint: \(memoryUsage(ofDecompressionContext: decompressionContext)) bytes\n") + } +} + +// MARK: - Demo 3: streaming compress / decompress + +extension ZstdExample { + /// Streams the payload through the compressor in 4 kiB chunks, then streams the compressed bytes back through the decompressor. + static func streamingDemo(payload: [UInt8]) throws { + print("# streaming (chunked compress + decompress)") + + let chunkSize = 4_096 + + guard let compressionContext = createCompressionContext() else { + throw ZstdError.allocationFailed("createCompressionContext") + } + defer { _ = freeCompressionContext(compressionContext) } + + try check(setCompressionParameter(compressionContext, .compressionLevel, to: 5)) + + let compressed = try streamCompress(payload, using: compressionContext, chunkSize: chunkSize) + + guard let decompressionContext = createDecompressionContext() else { + throw ZstdError.allocationFailed("createDecompressionContext") + } + defer { _ = freeDecompressionContext(decompressionContext) } + + let decompressed = try streamDecompress(compressed, using: decompressionContext, chunkSize: chunkSize) + + precondition(decompressed == payload) + + let chunkCount = (payload.count + chunkSize - 1) / chunkSize + print(" \(payload.count) → \(compressed.count) bytes streamed in \(chunkCount) chunks (\(ratio(of: payload.count, to: compressed.count)))\n") + } + + /// Drives ZSTD_compressStream2 manually, demonstrating the `compressStream(_:output:input:endOp:)` function and the `InputBuffer` / `OutputBuffer` value types. + /// (`compressStream` is overloaded — the 3-argument variant maps to ZSTD_compressStream and the 4-argument variant maps to ZSTD_compressStream2.) + static func streamCompress(_ input: [UInt8], + using context: OpaquePointer, + chunkSize: Int) throws -> [UInt8] { + let outBufferSize = compressionStreamOutputSize() + var outBuffer = [UInt8](repeating: 0, count: outBufferSize) + var compressed = [UInt8]() + + var sourcePosition = 0 + + while true { + let chunkEnd = min(sourcePosition + chunkSize, input.count) + let isLast = (chunkEnd == input.count) + let endOp: EndDirective = isLast ? .end : .continue + + let done: Bool = try input.withUnsafeBufferPointer { source in + try outBuffer.withUnsafeMutableBufferPointer { destination -> Bool in + var inBuf = InputBuffer( + source: UnsafeRawPointer(source.baseAddress!.advanced(by: sourcePosition)), + size: chunkEnd - sourcePosition, + position: 0) + + while true { + var outBuf = OutputBuffer(destination: UnsafeMutableRawPointer(destination.baseAddress!), + size: destination.count, + position: 0) + + let remaining = try check( + compressStream(context, + output: &outBuf, + input: &inBuf, + directive: endOp) + ) + + compressed.append(contentsOf: + UnsafeBufferPointer(start: destination.baseAddress, count: outBuf.position)) + + if isLast { + if remaining == 0 { + return true + } + } else { + if inBuf.position == inBuf.size { + return false + } + } + } + } + } + + if done { + break + } + + sourcePosition = chunkEnd + } + + return compressed + } + + /// Drives ZSTD_decompressStream manually. + static func streamDecompress(_ input: [UInt8], + using decompressionContext: OpaquePointer, + chunkSize: Int) throws -> [UInt8] { + let outBufferSize = decompressionStreamOutputSize() + var outBuffer = [UInt8](repeating: 0, count: outBufferSize) + var decompressed = [UInt8]() + + var sourcePosition = 0 + + while sourcePosition < input.count { + let chunkEnd = min(sourcePosition + chunkSize, input.count) + + try input.withUnsafeBufferPointer { source in + try outBuffer.withUnsafeMutableBufferPointer { destination in + var inBuf = InputBuffer(source: UnsafeRawPointer(source.baseAddress!.advanced(by: sourcePosition)), + size: chunkEnd - sourcePosition, + position: 0) + + while inBuf.position < inBuf.size { + var outBuf = OutputBuffer(destination: UnsafeMutableRawPointer(destination.baseAddress!), + size: destination.count, + position: 0) + + try check( + decompressStream(decompressionContext, output: &outBuf, input: &inBuf) + ) + + decompressed.append(contentsOf: UnsafeBufferPointer(start: destination.baseAddress, count: outBuf.position)) + } + } + } + + sourcePosition = chunkEnd + } + + return decompressed + } +} + +// MARK: - Demo 4: dictionary compression and Sendable CDict + +extension ZstdExample { + /// Builds a "raw content" dictionary from a phrase, then uses it to compress and decompress short messages. Finishes by sharing the same dictionary across four concurrent tasks — possible because the `CDict`'s underlying type is annotated `@unchecked Sendable`. + static func dictionaryDemo() async throws { + print("# dictionary compression with CDict / DDict") + + let dictionaryBytes = Array("The quick brown fox jumps over the lazy dog. ".utf8) + + guard let compressionDictionary = (dictionaryBytes.withUnsafeBufferPointer { bytes in + createCompressionDictionary(from: UnsafeRawPointer(bytes.baseAddress!), + size: bytes.count, + level: 5) + }) else { + throw ZstdError.allocationFailed("createCompressionDictionary") + } + defer { _ = freeCompressionDictionary(compressionDictionary) } + + guard let decompressionDictionary = (dictionaryBytes.withUnsafeBufferPointer { bytes in + createDecompressionDictionary(from: UnsafeRawPointer(bytes.baseAddress!), + size: bytes.count) + }) else { + throw ZstdError.allocationFailed("createDecompressionDictionary") + } + defer { _ = freeDecompressionDictionary(decompressionDictionary) } + + print(" CDict id = \(dictionaryID(fromCompressionDictionary: compressionDictionary)), memory = \(memoryUsage(ofCompressionDictionary: compressionDictionary)) bytes") + print(" DDict id = \(dictionaryID(fromDecompressionDictionary: decompressionDictionary)), memory = \(memoryUsage(ofDecompressionDictionary: decompressionDictionary)) bytes") + + guard let compressionContext = createCompressionContext() else { + throw ZstdError.allocationFailed("createCompressionContext") + } + defer { _ = freeCompressionContext(compressionContext) } + + guard let decompressionContext = createDecompressionContext() else { + throw ZstdError.allocationFailed("createDecompressionContext") + } + defer { _ = freeDecompressionContext(decompressionContext) } + + let sampleInput = Array("The quick brown fox jumps over the lazy dog.".utf8) + let bound = compressionBound(sampleInput.count) + var compressed = [UInt8](repeating: 0, count: bound) + + let compressedSize = try check( + sampleInput.withUnsafeBufferPointer { source in + compressed.withUnsafeMutableBufferPointer { destination in + compress(compressionContext, + into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count, + dictionary: compressionDictionary) + } + } + ) + compressed.removeLast(bound - compressedSize) + + var decompressed = [UInt8](repeating: 0, count: sampleInput.count) + let decompressedSize = try check( + compressed.withUnsafeBufferPointer { source in + decompressed.withUnsafeMutableBufferPointer { destination in + decompress(decompressionContext, + into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count, + dictionary: decompressionDictionary) + } + } + ) + + precondition(decompressedSize == sampleInput.count) + precondition(decompressed == sampleInput) + + print(" short message: \(sampleInput.count) → \(compressedSize) bytes\n") + + // Sendable dictionary: share across concurrent tasks + print("# concurrent CDict sharing (Sendable)") + + let sharedDictionary = SendableOpaquePointer(pointer: compressionDictionary) + + try await withThrowingTaskGroup(of: (Int, Int).self) { group in + for taskID in 0..<4 { + group.addTask { + guard let compressionContext = createCompressionContext() else { + throw ZstdError.allocationFailed("createCompressionContext") + } + defer { _ = freeCompressionContext(compressionContext) } + + let phrase = "Task \(taskID): The quick brown fox jumps over the lazy dog." + let bytes = Array(phrase.utf8) + let bound = compressionBound(bytes.count) + var out = [UInt8](repeating: 0, count: bound) + + let n = bytes.withUnsafeBufferPointer { source in + out.withUnsafeMutableBufferPointer { destination in + compress(compressionContext, + into: destination.baseAddress!, + capacity: destination.count, + from: source.baseAddress!, + size: source.count, + dictionary: sharedDictionary.pointer) + } + } + + return (taskID, n) + } + } + + for try await (taskID, size) in group { + print(" task \(taskID) → \(size) bytes") + } + } + } +} diff --git a/Sources/zstd-example/dump-api.sh b/Sources/zstd-example/dump-api.sh new file mode 100755 index 00000000000..de16034fd03 --- /dev/null +++ b/Sources/zstd-example/dump-api.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +# This is a helper to show what the Swift API looks like — full signatures +# including parameter and return types, optionality, etc. + +xcrun swift-api-digester \ + -dump-sdk \ + -module Zstd \ + -o /tmp/zstd-api.json \ + -I lib \ + -I Sources/Zstd/include + +python3 <<'PY' +import json + +with open('/tmp/zstd-api.json') as f: + d = json.load(f) + +root = d.get('ABIRoot', d) +top = root.get('children', []) + +# Hide the C-builtin typedefs that the importer drags in. +SKIP_TYPEALIAS = {'__NSConstantString', '__builtin_ms_va_list', '__builtin_va_list', + 'ptrdiff_t', 'rsize_t', 'size_t', 'wchar_t'} + +# Swift keywords that need to be backticked when used as identifiers. +SWIFT_KEYWORDS = { + 'continue', 'break', 'case', 'class', 'default', 'else', 'for', 'if', + 'in', 'let', 'var', 'while', 'return', 'switch', 'do', 'try', 'throw', + 'init', 'func', 'enum', 'struct', 'protocol', 'extension', 'where', + 'self', 'Self', 'super', 'true', 'false', 'nil', 'fallthrough', + 'guard', 'defer', 'repeat', 'is', 'as', 'throws', 'rethrows', 'async', + 'await', 'inout', 'operator', 'precedencegroup', 'subscript', +} + +def strip_module(t: str) -> str: + """Remove common module prefixes for readability.""" + if not t: + return t + return t.replace('Swift.', '').replace('Zstd.', '') + +def backtick(name: str) -> str: + return f"`{name}`" if name in SWIFT_KEYWORDS else name + +def type_children(node): + """Return only the type-shaped children (parameters / return type).""" + return [c for c in node.get('children', []) + if c.get('kind', '').startswith('Type') + and c.get('kind') != 'TypeAlias'] + +def split_signature(printed: str): + """Split 'foo(a:b:c:)' into ('foo', ['a','b','c']).""" + if '(' not in printed: + return printed, [] + base, _, rest = printed.partition('(') + return base, [l for l in rest.rstrip(')').split(':') if l] + +def emit_function(node, indent: str = '') -> str: + name, labels = split_signature(node.get('printedName', node['name'])) + types = type_children(node) + if types: + ret = strip_module(types[0].get('printedName', '?')) + params = [strip_module(t.get('printedName', '?')) for t in types[1:]] + else: + ret, params = '?', [] + + is_init = node.get('declKind') == 'Constructor' + if is_init: + # Constructors include the Self type as the first "param type" in the + # JSON dump; drop it since it isn't actually written at the call site. + params = params # params already excludes ret; for init, treat all as actual params + pieces = [] + for i, lbl in enumerate(labels): + t = params[i] if i < len(params) else '?' + pieces.append(f"_: {t}" if lbl == '_' else f"{lbl}: {t}") + params_str = ', '.join(pieces) + + if is_init: + return f"{indent}init({params_str})" + ret_part = '' if ret in ('()', 'Void') else f" -> {ret}" + return f"{indent}func {backtick(name)}({params_str}){ret_part}" + +def emit_var(node, indent: str = '', top_level: bool = False) -> str: + name = backtick(node.get('printedName', node['name'])) + decl = node.get('declKind', 'Var') + if decl == 'EnumElement': + return f"{indent}case {name}" + types = type_children(node) + t = strip_module(types[0].get('printedName', '?')) if types else '?' + keyword = 'let' if top_level else 'var' + suffix = '' if top_level else ' { get }' + return f"{indent}{keyword} {name}: {t}{suffix}" + +def emit_typealias(node, indent: str = '') -> str: + name = node.get('printedName', node['name']) + types = type_children(node) + aliased = strip_module(types[0].get('printedName', '?')) if types else '?' + return f"{indent}typealias {name} = {aliased}" + +def banner(title: str): + print('\n' + '=' * 70) + print(title) + print('=' * 70) + +by_kind = {} +for c in top: + k = c.get('kind', '') + if k == 'Import': + continue + if k == 'TypeAlias' and c.get('name') in SKIP_TYPEALIAS: + continue + by_kind.setdefault(k, []).append(c) + +# ---- Types ----------------------------------------------------------------- +banner(f"TYPES ({len(by_kind.get('TypeDecl', []))})") +for c in sorted(by_kind.get('TypeDecl', []), key=lambda x: x['name']): + print(f"\n {c['name']}") + for m in c.get('children', []): + mk = m.get('kind', '') + decl = m.get('declKind', '') + if mk == 'TypeAlias': + # Skip the synthesised .RawValue alias inside imported enums. + if m.get('name') == 'RawValue': + continue + print(emit_typealias(m, indent=' ')) + elif decl == 'Constructor' or mk == 'Constructor': + print(emit_function(m, indent=' ')) + elif mk == 'Function': + print(emit_function(m, indent=' ')) + elif mk == 'Var': + print(emit_var(m, indent=' ')) + +# ---- Typealiases (top-level) ---------------------------------------------- +banner(f"TYPEALIASES ({len(by_kind.get('TypeAlias', []))})") +for c in sorted(by_kind.get('TypeAlias', []), key=lambda x: x['name']): + print(' ' + emit_typealias(c)) + +# ---- Constants ------------------------------------------------------------ +banner(f"CONSTANTS ({len(by_kind.get('Var', []))})") +for c in sorted(by_kind.get('Var', []), key=lambda x: x['name']): + print(' ' + emit_var(c, top_level=True)) + +# ---- Functions ------------------------------------------------------------ +funcs = by_kind.get('Function', []) +banner(f"FUNCTIONS ({len(funcs)})") +for c in sorted(funcs, key=lambda x: x.get('printedName', x['name'])): + print(' ' + emit_function(c)) +PY diff --git a/build/VS2008/fullbench/fullbench.vcproj b/build/VS2008/fullbench/fullbench.vcproj index 5e349dce956..eb254471036 100644 --- a/build/VS2008/fullbench/fullbench.vcproj +++ b/build/VS2008/fullbench/fullbench.vcproj @@ -462,6 +462,10 @@ RelativePath="..\..\..\lib\common\error_private.h" > + + diff --git a/build/VS2008/fuzzer/fuzzer.vcproj b/build/VS2008/fuzzer/fuzzer.vcproj index 32f28468473..703470de2d6 100644 --- a/build/VS2008/fuzzer/fuzzer.vcproj +++ b/build/VS2008/fuzzer/fuzzer.vcproj @@ -482,6 +482,10 @@ RelativePath="..\..\..\lib\common\error_private.h" > + + diff --git a/build/VS2008/zstd/zstd.vcproj b/build/VS2008/zstd/zstd.vcproj index fc87625a950..44a8fa36eda 100644 --- a/build/VS2008/zstd/zstd.vcproj +++ b/build/VS2008/zstd/zstd.vcproj @@ -582,6 +582,10 @@ RelativePath="..\..\..\lib\zstd.h" > + + diff --git a/build/VS2008/zstdlib/zstdlib.vcproj b/build/VS2008/zstdlib/zstdlib.vcproj index 61c88f5bcb4..146d70cb008 100644 --- a/build/VS2008/zstdlib/zstdlib.vcproj +++ b/build/VS2008/zstdlib/zstdlib.vcproj @@ -494,6 +494,10 @@ RelativePath="..\..\..\lib\common\error_private.h" > + + diff --git a/build/VS2010/fullbench/fullbench.vcxproj b/build/VS2010/fullbench/fullbench.vcxproj index c78a72eccdd..04bf3b809e9 100644 --- a/build/VS2010/fullbench/fullbench.vcxproj +++ b/build/VS2010/fullbench/fullbench.vcxproj @@ -192,6 +192,7 @@ + diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj index ccbd2517de9..847019232bd 100644 --- a/build/VS2010/fuzzer/fuzzer.vcxproj +++ b/build/VS2010/fuzzer/fuzzer.vcxproj @@ -197,6 +197,7 @@ + diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj index ddb8e3216f5..6a0bb718236 100644 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj @@ -62,6 +62,7 @@ + diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index 09ead245a64..3a2f869c4e7 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -62,6 +62,7 @@ + diff --git a/build/VS2010/zstd/zstd.vcxproj b/build/VS2010/zstd/zstd.vcxproj index 230fd7d09e7..265b1595603 100644 --- a/build/VS2010/zstd/zstd.vcxproj +++ b/build/VS2010/zstd/zstd.vcxproj @@ -80,6 +80,7 @@ + diff --git a/build/meson/lib/meson.build b/build/meson/lib/meson.build index 81fc313f954..b37ba27e8ae 100644 --- a/build/meson/lib/meson.build +++ b/build/meson/lib/meson.build @@ -172,4 +172,5 @@ pkgconfig.generate(libzstd, install_headers(join_paths(zstd_rootdir, 'lib/zstd.h'), join_paths(zstd_rootdir, 'lib/zdict.h'), - join_paths(zstd_rootdir, 'lib/zstd_errors.h')) + join_paths(zstd_rootdir, 'lib/zstd_errors.h'), + join_paths(zstd_rootdir, 'lib/zstd_annotations.h')) diff --git a/build/single_file_libs/build_library_test.sh b/build/single_file_libs/build_library_test.sh index b67cd99a0f2..e0095968f9c 100755 --- a/build/single_file_libs/build_library_test.sh +++ b/build/single_file_libs/build_library_test.sh @@ -71,6 +71,7 @@ echo "Single file library creation script: PASSED" # Copy the header to here (for the tests) cp "$ZSTD_SRC_ROOT/zstd.h" examples/zstd.h cp "$ZSTD_SRC_ROOT/zstd_errors.h" examples/zstd_errors.h +cp "$ZSTD_SRC_ROOT/zstd_annotations.h" examples/zstd_annotations.h # Compile the generated output cc -Wall -Wextra -Werror -Wshadow -pthread -I. -Os -g0 -o $OUT_FILE zstd.c examples/roundtrip.c diff --git a/build/single_file_libs/zstd-in.c b/build/single_file_libs/zstd-in.c index f381ecc4f56..0aa4ac759ac 100644 --- a/build/single_file_libs/zstd-in.c +++ b/build/single_file_libs/zstd-in.c @@ -34,6 +34,17 @@ * * Note: multithreading is enabled for all platforms apart from Emscripten. */ +/* The amalgamation concatenates zstd's public headers (which carry + * nullability annotations) with the internal headers (which don't), in + * a single translation unit. That trips clang's `-Wnullability- + * completeness` on the unannotated internal declarations. Suppress + * the warning here, at the very top of the amalgam, so it covers every + * line that follows. */ +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wnullability-completeness" +#pragma clang diagnostic ignored "-Wnullability-extension" +#endif + #define DEBUGLEVEL 0 #define MEM_MODULE #undef XXH_NAMESPACE diff --git a/build/single_file_libs/zstddeclib-in.c b/build/single_file_libs/zstddeclib-in.c index 8d9c1f54bb7..e55eaf9fd17 100644 --- a/build/single_file_libs/zstddeclib-in.c +++ b/build/single_file_libs/zstddeclib-in.c @@ -32,6 +32,17 @@ * re-running without the "-x legacy/zstd_legacy.h" option (it excludes the * legacy support at the source level). */ +/* The amalgamation concatenates zstd's public headers (which carry + * nullability annotations) with the internal headers (which don't), in + * a single translation unit. That trips clang's `-Wnullability- + * completeness` on the unannotated internal declarations. Suppress + * the warning here, at the very top of the amalgam, so it covers every + * line that follows. */ +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wnullability-completeness" +#pragma clang diagnostic ignored "-Wnullability-extension" +#endif + #define DEBUGLEVEL 0 #define MEM_MODULE #undef XXH_NAMESPACE diff --git a/contrib/freestanding_lib/freestanding.py b/contrib/freestanding_lib/freestanding.py index df6983245d6..294b8253c8e 100755 --- a/contrib/freestanding_lib/freestanding.py +++ b/contrib/freestanding_lib/freestanding.py @@ -483,6 +483,7 @@ def _copy_source_lib(self): os.makedirs(self._dst_lib, exist_ok=True) self._copy_file("zstd.h") self._copy_file("zstd_errors.h") + self._copy_file("zstd_annotations.h") for subdir in INCLUDED_SUBDIRS: src_dir = os.path.join(self._src_lib, subdir) dst_dir = os.path.join(self._dst_lib, subdir) diff --git a/contrib/linux-kernel/Makefile b/contrib/linux-kernel/Makefile index 63dd15d958f..1c4c26671b4 100644 --- a/contrib/linux-kernel/Makefile +++ b/contrib/linux-kernel/Makefile @@ -24,6 +24,7 @@ libzstd: --rewrite-include '=' \ --rewrite-include '"\.\./zstd.h"=' \ --rewrite-include '"(\.\./)?zstd_errors.h"=' \ + --rewrite-include '"(\.\./)?zstd_annotations.h"=' \ --sed 's,/\*\*\*,/* *,g' \ --sed 's,/\*\*,/*,g' \ --spdx \ @@ -59,6 +60,7 @@ libzstd: rm linux/lib/zstd/decompress/huf_decompress_amd64.S mv linux/lib/zstd/zstd.h linux/include/linux/zstd_lib.h mv linux/lib/zstd/zstd_errors.h linux/include/linux/ + mv linux/lib/zstd/zstd_annotations.h linux/include/linux/ cp linux_zstd.h linux/include/linux/zstd.h cp zstd_common_module.c linux/lib/zstd cp zstd_compress_module.c linux/lib/zstd @@ -72,10 +74,12 @@ LINUX ?= $(HOME)/repos/linux import: libzstd rm -f $(LINUX)/include/linux/zstd.h rm -f $(LINUX)/include/linux/zstd_errors.h + rm -f $(LINUX)/include/linux/zstd_annotations.h rm -rf $(LINUX)/lib/zstd cp linux/include/linux/zstd.h $(LINUX)/include/linux cp linux/include/linux/zstd_lib.h $(LINUX)/include/linux cp linux/include/linux/zstd_errors.h $(LINUX)/include/linux + cp linux/include/linux/zstd_annotations.h $(LINUX)/include/linux cp -r linux/lib/zstd $(LINUX)/lib import-upstream: @@ -86,6 +90,7 @@ import-upstream: cp -r ../../lib/compress $(LINUX)/lib/zstd cp -r ../../lib/decompress $(LINUX)/lib/zstd mv $(LINUX)/lib/zstd/zstd_errors.h $(LINUX)/include/linux + mv $(LINUX)/lib/zstd/zstd_annotations.h $(LINUX)/include/linux rm $(LINUX)/lib/zstd/common/threading.* rm $(LINUX)/lib/zstd/common/pool.* rm $(LINUX)/lib/zstd/common/xxhash.* diff --git a/lib/Makefile b/lib/Makefile index 569bd6090c9..e62161e769b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -372,6 +372,7 @@ install-includes: @echo Installing includes $(INSTALL_DATA) zstd.h $(DESTDIR)$(INCLUDEDIR) $(INSTALL_DATA) zstd_errors.h $(DESTDIR)$(INCLUDEDIR) + $(INSTALL_DATA) zstd_annotations.h $(DESTDIR)$(INCLUDEDIR) $(INSTALL_DATA) zdict.h $(DESTDIR)$(INCLUDEDIR) .PHONY: uninstall @@ -383,6 +384,7 @@ uninstall: $(RM) $(DESTDIR)$(PKGCONFIGDIR)/libzstd.pc $(RM) $(DESTDIR)$(INCLUDEDIR)/zstd.h $(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_errors.h + $(RM) $(DESTDIR)$(INCLUDEDIR)/zstd_annotations.h $(RM) $(DESTDIR)$(INCLUDEDIR)/zdict.h @echo zstd libraries successfully uninstalled diff --git a/lib/module.modulemap b/lib/module.modulemap index e66a210d06b..0c3955cae82 100644 --- a/lib/module.modulemap +++ b/lib/module.modulemap @@ -1,4 +1,7 @@ -module libzstd [extern_c] { +// Private modulemap for the _ZstdCore implementation target. +// The actual public Swift modules live in the Zstd and libzstd targets' +// own modulemaps. This module is not intended for client use. +module _ZstdCore [extern_c] { header "zstd.h" export * diff --git a/lib/zdict.h b/lib/zdict.h index 599b793013b..8cee3a11b62 100644 --- a/lib/zdict.h +++ b/lib/zdict.h @@ -15,6 +15,12 @@ /*====== Dependencies ======*/ #include /* size_t */ +#include "zstd_annotations.h" + +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull begin +#endif + #if defined (__cplusplus) extern "C" { #endif @@ -275,11 +281,19 @@ ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); } #endif +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull end +#endif + #endif /* ZSTD_ZDICT_H */ #if defined(ZDICT_STATIC_LINKING_ONLY) && !defined(ZSTD_ZDICT_H_STATIC) #define ZSTD_ZDICT_H_STATIC +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull begin +#endif + #if defined (__cplusplus) extern "C" { #endif @@ -478,4 +492,8 @@ size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize } #endif +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull end +#endif + #endif /* ZSTD_ZDICT_H_STATIC */ diff --git a/lib/zstd.h b/lib/zstd.h index 97fef316fd6..4901018c37a 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -15,11 +15,24 @@ /* ====== Dependencies ======*/ #include /* size_t */ +/* All the macros that decorate this header for Swift import / clang + * static analysis are defined in a shared file — see that header for + * details on each macro and the ZSTD_NULLABILITY override knob. */ +#include "zstd_annotations.h" + #include "zstd_errors.h" /* list of errors */ #if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) #include /* INT_MAX */ #endif /* ZSTD_STATIC_LINKING_ONLY */ +/* Pointers in the API below are nonnull unless explicitly tagged + * ZSTD_NULLABLE. Gated on ZSTD_NULLABILITY (default-on for clang) so + * the legacy libzstd umbrella can switch back to unspecified + * nullability by `#define ZSTD_NULLABILITY 0` before inclusion. */ +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull begin +#endif + #if defined (__cplusplus) extern "C" { #endif @@ -157,8 +170,8 @@ ZSTDLIB_API const char* ZSTD_versionString(void); * enough space to successfully compress the data. * @return : compressed size written into `dst` (<= `dstCapacity), * or an error code if it fails (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, - const void* src, size_t srcSize, +ZSTDLIB_API size_t ZSTD_compress( void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, int compressionLevel); /*! ZSTD_decompress() : @@ -170,8 +183,8 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, * If maximum upper bound isn't known, prefer using streaming mode to decompress data. * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, - const void* src, size_t compressedSize); +ZSTDLIB_API size_t ZSTD_decompress( void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t compressedSize); /*====== Decompression helper functions ======*/ @@ -278,8 +291,8 @@ ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compress * use one different context per thread . */ typedef struct ZSTD_CCtx_s ZSTD_CCtx; -ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); -ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* compatible with NULL pointer */ +ZSTDLIB_API ZSTD_CCtx* ZSTD_NULLABLE ZSTD_createCCtx(void); +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* ZSTD_NULLABLE cctx); /*! ZSTD_compressCCtx() : * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. @@ -290,8 +303,8 @@ ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* compatible with NULL * they will all be reset. Only @compressionLevel remains. */ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, int compressionLevel); /*= Decompression context @@ -301,8 +314,8 @@ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, * This will make workload friendlier for system's memory. * Use one context per thread for parallel execution. */ typedef struct ZSTD_DCtx_s ZSTD_DCtx; -ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); -ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */ +ZSTDLIB_API ZSTD_DCtx* ZSTD_NULLABLE ZSTD_createDCtx(void); +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* ZSTD_NULLABLE dctx); /*! ZSTD_decompressDCtx() : * Same as ZSTD_decompress(), @@ -310,8 +323,8 @@ ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer * * Compatible with sticky parameters (see below). */ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize); + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize); /********************************************* @@ -332,21 +345,23 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, */ -/* Compression strategies, listed from fastest to strongest */ -typedef enum { ZSTD_fast=1, - ZSTD_dfast=2, - ZSTD_greedy=3, - ZSTD_lazy=4, - ZSTD_lazy2=5, - ZSTD_btlazy2=6, - ZSTD_btopt=7, - ZSTD_btultra=8, - ZSTD_btultra2=9 +/* Compression strategies, listed from fastest to strongest. + * Marked open: zstd reserves the right to add new strategies in the future. */ +typedef enum ZSTD_ENUM_OPEN { + ZSTD_fast=1, + ZSTD_dfast=2, + ZSTD_greedy=3, + ZSTD_lazy=4, + ZSTD_lazy2=5, + ZSTD_btlazy2=6, + ZSTD_btopt=7, + ZSTD_btultra=8, + ZSTD_btultra2=9 /* note : new strategies _might_ be added in the future. Only the order (from fast to strong) is guaranteed */ } ZSTD_strategy; -typedef enum { +typedef enum ZSTD_ENUM_OPEN { /* compression parameters * Note: When compressing with a ZSTD_CDict these parameters are superseded @@ -586,7 +601,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param */ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_reset_session_only = 1, ZSTD_reset_parameters = 2, ZSTD_reset_session_and_parameters = 3 @@ -621,8 +636,8 @@ ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset); * or an error code if it fails (which can be tested using ZSTD_isError()). */ ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize); + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize); /*********************************************** @@ -637,7 +652,7 @@ ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, * Therefore, no new decompression function is necessary. */ -typedef enum { +typedef enum ZSTD_ENUM_OPEN { ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which * the streaming API will refuse to allocate memory buffer @@ -699,15 +714,15 @@ ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); ****************************/ typedef struct ZSTD_inBuffer_s { - const void* src; /**< start of input buffer */ - size_t size; /**< size of input buffer */ - size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ + const void* ZSTD_NULLABLE src ZSTD_SWIFT_FIELD("source"); /**< start of input buffer */ + size_t size; /**< size of input buffer */ + size_t pos ZSTD_SWIFT_FIELD("position"); /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ } ZSTD_inBuffer; typedef struct ZSTD_outBuffer_s { - void* dst; /**< start of output buffer */ - size_t size; /**< size of output buffer */ - size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ + void* ZSTD_NULLABLE dst ZSTD_SWIFT_FIELD("destination"); /**< start of output buffer */ + size_t size; /**< size of output buffer */ + size_t pos ZSTD_SWIFT_FIELD("position"); /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ } ZSTD_outBuffer; @@ -776,11 +791,11 @@ typedef struct ZSTD_outBuffer_s { typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ /*===== ZSTD_CStream management functions =====*/ -ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); -ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */ +ZSTDLIB_API ZSTD_CStream* ZSTD_NULLABLE ZSTD_createCStream(void); +ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* ZSTD_NULLABLE zcs); /*===== Streaming compression functions =====*/ -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ ZSTD_e_flush=1, /* flush any data provided so far, * it creates (at least) one new block, that can be decoded immediately on reception; @@ -908,8 +923,8 @@ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ /*===== ZSTD_DStream management functions =====*/ -ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); -ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */ +ZSTDLIB_API ZSTD_DStream* ZSTD_NULLABLE ZSTD_createDStream(void); +ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* ZSTD_NULLABLE zds); /*===== Streaming decompression functions =====*/ @@ -962,9 +977,9 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output * It's intended for a dictionary used only once. * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, int compressionLevel); /*! ZSTD_decompress_usingDict() : @@ -974,9 +989,9 @@ ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, * It's intended for a dictionary used only once. * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize); + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, + const void* ZSTD_NULLABLE dict, size_t dictSize); /*********************************** @@ -996,13 +1011,14 @@ typedef struct ZSTD_CDict_s ZSTD_CDict; * in which case the only thing that it transports is the @compressionLevel. * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively, * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */ -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, - int compressionLevel); +ZSTDLIB_API ZSTD_CDict* ZSTD_NULLABLE ZSTD_createCDict(const void* ZSTD_NULLABLE dictBuffer, + size_t dictSize, + int compressionLevel); /*! ZSTD_freeCDict() : * Function frees memory allocated by ZSTD_createCDict(). * If a NULL pointer is passed, no operation is performed. */ -ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); +ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* ZSTD_NULLABLE CDict); /*! ZSTD_compress_usingCDict() : * Compression using a digested Dictionary. @@ -1010,8 +1026,8 @@ ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); * Note : compression level is _decided at dictionary creation time_, * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */ ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, const ZSTD_CDict* cdict); @@ -1020,20 +1036,21 @@ typedef struct ZSTD_DDict_s ZSTD_DDict; /*! ZSTD_createDDict() : * Create a digested dictionary, ready to start decompression operation without startup delay. * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */ -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); +ZSTDLIB_API ZSTD_DDict* ZSTD_NULLABLE ZSTD_createDDict(const void* ZSTD_NULLABLE dictBuffer, + size_t dictSize); /*! ZSTD_freeDDict() : * Function frees memory allocated with ZSTD_createDDict() * If a NULL pointer is passed, no operation is performed. */ -ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); +ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ZSTD_NULLABLE ddict); /*! ZSTD_decompress_usingDDict() : * Decompression using a digested Dictionary. * Recommended when same dictionary is used multiple times. */ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_DDict* ddict); + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, + const ZSTD_DDict* ZSTD_NULLABLE ddict); /******************************** @@ -1044,19 +1061,19 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, * Provides the dictID stored within dictionary. * if @return == 0, the dictionary is not conformant with Zstandard specification. * It can still be loaded, but as a content-only dictionary. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); +ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* ZSTD_NULLABLE dict, size_t dictSize); /*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+ * Provides the dictID of the dictionary loaded into `cdict`. * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict); +ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* ZSTD_NULLABLE cdict); /*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+ * Provides the dictID of the dictionary loaded into `ddict`. * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); +ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ZSTD_NULLABLE ddict); /*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+ * Provides the dictID required to decompressed the frame stored within `src`. @@ -1105,7 +1122,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); * If you want to employ LDM on some large dictionary content, * prefer employing ZSTD_CCtx_refPrefix() described below. */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* ZSTD_NULLABLE dict, size_t dictSize); /*! ZSTD_CCtx_refCDict() : Requires v1.4.0+ * Reference a prepared dictionary, to be used for all future compressed frames. @@ -1119,7 +1136,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s * Note 1 : Currently, only one dictionary can be managed. * Referencing a new dictionary effectively "discards" any previous one. * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ -ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); +ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* ZSTD_NULLABLE cdict); /*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+ * Reference a prefix (single-usage dictionary) for next compressed frame. @@ -1141,7 +1158,8 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent). * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, - const void* prefix, size_t prefixSize); + const void* ZSTD_NULLABLE prefix, + size_t prefixSize); /*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+ * Create an internal DDict from dict buffer, to be used to decompress all future frames. @@ -1158,7 +1176,9 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of * how dictionary content is loaded and interpreted. */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, + const void* ZSTD_NULLABLE dict, + size_t dictSize); /*! ZSTD_DCtx_refDDict() : Requires v1.4.0+ * Reference a prepared dictionary, to be used to decompress next frames. @@ -1177,7 +1197,8 @@ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, s * Special: referencing a NULL DDict means "return to no-dictionary mode". * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. */ -ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); +ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, + const ZSTD_DDict* ZSTD_NULLABLE ddict); /*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+ * Reference a prefix (single-usage dictionary) to decompress next frame. @@ -1196,7 +1217,8 @@ ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); * A full dictionary is more costly, as it requires building tables. */ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, - const void* prefix, size_t prefixSize); + const void* ZSTD_NULLABLE prefix, + size_t prefixSize); /* === Memory management === */ @@ -1214,6 +1236,10 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); } #endif +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull end +#endif + #endif /* ZSTD_H_235446 */ @@ -1229,6 +1255,10 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); #if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) #define ZSTD_H_ZSTD_STATIC_LINKING_ONLY +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull begin +#endif + #if defined (__cplusplus) extern "C" { #endif @@ -1370,37 +1400,37 @@ typedef struct { ZSTD_frameParameters fParams; } ZSTD_parameters; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */ } ZSTD_dictContentType_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ ZSTD_dlm_byRef = 1 /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ } ZSTD_dictLoadMethod_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number. * Useful to save 4 bytes per generated frame. * Decoder cannot recognise automatically this format, requiring this instruction. */ } ZSTD_format_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */ ZSTD_d_validateChecksum = 0, ZSTD_d_ignoreChecksum = 1 } ZSTD_forceIgnoreChecksum_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { /* Note: this enum controls ZSTD_d_refMultipleDDicts */ ZSTD_rmd_refSingleDDict = 0, ZSTD_rmd_refMultipleDDicts = 1 } ZSTD_refMultipleDDicts_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { /* Note: this enum and the behavior it controls are effectively internal * implementation details of the compressor. They are expected to continue * to evolve and should be considered only in the context of extremely @@ -1439,7 +1469,7 @@ typedef enum { ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ } ZSTD_dictAttachPref_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level. * Negative compression levels will be uncompressed, and positive compression * levels will be compressed. */ @@ -1448,7 +1478,7 @@ typedef enum { ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ } ZSTD_literalCompressionMode_e; -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { /* Note: This enum controls features which are conditionally beneficial. * Zstd can take a decision on whether or not to enable the feature (ZSTD_ps_auto), * but setting the switch to ZSTD_ps_enable or ZSTD_ps_disable force enable/disable the feature. @@ -1507,7 +1537,7 @@ ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size * or an error code (if srcSize is too small) */ ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); -typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e; +typedef enum ZSTD_ENUM_CLOSED { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e; #define ZSTD_frameType_e ZSTD_FrameType_e /* old name */ typedef struct { unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ @@ -1578,7 +1608,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSi (blockSize) /* One block of margin */ \ )) -typedef enum { +typedef enum ZSTD_ENUM_CLOSED { ZSTD_sf_noBlockDelimiters = 0, /* ZSTD_Sequence[] has no block delimiters, just sequences */ ZSTD_sf_explicitBlockDelimiters = 1 /* ZSTD_Sequence[] contains explicit block delimiters */ } ZSTD_SequenceFormat_e; @@ -1737,8 +1767,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity * * @return : number of bytes written or a ZSTD error. */ -ZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, - unsigned* magicVariant, +ZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* ZSTD_NULLABLE dst, size_t dstCapacity, + unsigned* ZSTD_NULLABLE magicVariant, const void* src, size_t srcSize); /*! ZSTD_isSkippableFrame() : @@ -1840,22 +1870,22 @@ ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadM * Limitation 2 : static cctx currently not compatible with multi-threading. * Limitation 3 : static dctx is incompatible with legacy support. */ -ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); -ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ +ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_NULLABLE ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_NULLABLE ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ -ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); -ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ +ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_NULLABLE ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_NULLABLE ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ -ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict( +ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_NULLABLE ZSTD_initStaticCDict( void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, ZSTD_compressionParameters cParams); -ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict( +ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_NULLABLE ZSTD_initStaticDDict( void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); @@ -1865,9 +1895,9 @@ ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict( * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. * All allocation/free operations will be completed using these custom variants instead of regular ones. */ -typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); -typedef void (*ZSTD_freeFunction) (void* opaque, void* address); -typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; +typedef void* ZSTD_NULLABLE (*ZSTD_allocFunction) (void* ZSTD_NULLABLE opaque, size_t size); +typedef void (*ZSTD_freeFunction) (void* ZSTD_NULLABLE opaque, void* ZSTD_NULLABLE address); +typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* ZSTD_NULLABLE opaque; } ZSTD_customMem; #if defined(__clang__) && __clang_major__ >= 5 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" @@ -1881,12 +1911,12 @@ ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constan #pragma clang diagnostic pop #endif -ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); -ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); -ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); -ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_NULLABLE ZSTD_createCCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_NULLABLE ZSTD_createCStream_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_NULLABLE ZSTD_createDCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_NULLABLE ZSTD_createDStream_advanced(ZSTD_customMem customMem); -ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_NULLABLE ZSTD_createCDict_advanced(const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, ZSTD_compressionParameters cParams, @@ -1903,23 +1933,23 @@ ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_ * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer. */ typedef struct POOL_ctx_s ZSTD_threadPool; -ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads); -ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */ -ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool); +ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_NULLABLE ZSTD_createThreadPool(size_t numThreads); +ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* ZSTD_NULLABLE pool); /* accept NULL pointer */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* ZSTD_NULLABLE pool); /* * This API is temporary and is expected to change or disappear in the future! */ -ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2( - const void* dict, size_t dictSize, +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_NULLABLE ZSTD_createCDict_advanced2( + const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, const ZSTD_CCtx_params* cctxParams, ZSTD_customMem customMem); -ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced( - const void* dict, size_t dictSize, +ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_NULLABLE ZSTD_createDDict_advanced( + const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, ZSTD_customMem customMem); @@ -1935,7 +1965,7 @@ ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced( * As a consequence, `dictBuffer` **must** outlive CDict, * and its content must remain unmodified throughout the lifetime of CDict. * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ -ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_NULLABLE ZSTD_createCDict_byReference(const void* ZSTD_NULLABLE dictBuffer, size_t dictSize, int compressionLevel); /*! ZSTD_getCParams() : * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. @@ -1988,9 +2018,9 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters p ZSTD_DEPRECATED("use ZSTD_compress2") ZSTDLIB_STATIC_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_parameters params); /*! ZSTD_compress_usingCDict_advanced() : @@ -2000,8 +2030,8 @@ size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary") ZSTDLIB_STATIC_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, + void* ZSTD_NULLABLE dst, size_t dstCapacity, + const void* ZSTD_NULLABLE src, size_t srcSize, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams); @@ -2009,18 +2039,18 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, /*! ZSTD_CCtx_loadDictionary_byReference() : * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx. * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */ -ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* ZSTD_NULLABLE dict, size_t dictSize); /*! ZSTD_CCtx_loadDictionary_advanced() : * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over * how to load the dictionary (by copy ? by reference ?) * and how to interpret it (automatic ? force raw mode ? full mode only ?) */ -ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); /*! ZSTD_CCtx_refPrefix_advanced() : * Same as ZSTD_CCtx_refPrefix(), but gives finer control over * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ -ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* ZSTD_NULLABLE prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); /* === experimental parameters === */ /* these parameters can be used with ZSTD_setParameter() @@ -2380,8 +2410,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cPa * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() * for static allocation of CCtx for single-threaded compression. */ -ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); -ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */ +ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_NULLABLE ZSTD_createCCtxParams(void); +ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* ZSTD_NULLABLE params); /* accept NULL pointer */ /*! ZSTD_CCtxParams_reset() : * Reset params to default values. @@ -2435,8 +2465,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( */ ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs ( ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos, + void* ZSTD_NULLABLE dst, size_t dstCapacity, size_t* dstPos, + const void* ZSTD_NULLABLE src, size_t srcSize, size_t* srcPos, ZSTD_EndDirective endOp); @@ -2456,26 +2486,26 @@ ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size); * Dictionary content is referenced, and therefore stays in dictBuffer. * It is important that dictBuffer outlives DDict, * it must remain read accessible throughout the lifetime of DDict */ -ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); +ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_NULLABLE ZSTD_createDDict_byReference(const void* ZSTD_NULLABLE dictBuffer, size_t dictSize); /*! ZSTD_DCtx_loadDictionary_byReference() : * Same as ZSTD_DCtx_loadDictionary(), * but references `dict` content instead of copying it into `dctx`. * This saves memory if `dict` remains around., * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */ -ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* ZSTD_NULLABLE dict, size_t dictSize); /*! ZSTD_DCtx_loadDictionary_advanced() : * Same as ZSTD_DCtx_loadDictionary(), * but gives direct control over * how to load the dictionary (by copy ? by reference ?) * and how to interpret it (automatic ? force raw mode ? full mode only ?). */ -ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); /*! ZSTD_DCtx_refPrefix_advanced() : * Same as ZSTD_DCtx_refPrefix(), but gives finer control over * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ -ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* ZSTD_NULLABLE prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); /*! ZSTD_DCtx_setMaxWindowSize() : * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. @@ -2610,8 +2640,8 @@ size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); */ ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs ( ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos); + void* ZSTD_NULLABLE dst, size_t dstCapacity, size_t* dstPos, + const void* ZSTD_NULLABLE src, size_t srcSize, size_t* srcPos); /******************************************************************** @@ -2656,7 +2686,7 @@ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") ZSTDLIB_STATIC_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, int compressionLevel); /*! ZSTD_initCStream_advanced() : @@ -2674,7 +2704,7 @@ size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") ZSTDLIB_STATIC_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); @@ -2776,7 +2806,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); * note: no dictionary will be used if dict == NULL or dictSize < 8 */ ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions") -ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); +ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* ZSTD_NULLABLE dict, size_t dictSize); /*! * This function is deprecated, and is equivalent to: @@ -2927,10 +2957,10 @@ ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); #define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1)) typedef size_t (*ZSTD_sequenceProducer_F) ( - void* sequenceProducerState, + void* ZSTD_NULLABLE sequenceProducerState, ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, const void* src, size_t srcSize, - const void* dict, size_t dictSize, + const void* ZSTD_NULLABLE dict, size_t dictSize, int compressionLevel, size_t windowSize ); @@ -2957,8 +2987,8 @@ typedef size_t (*ZSTD_sequenceProducer_F) ( ZSTDLIB_STATIC_API void ZSTD_registerSequenceProducer( ZSTD_CCtx* cctx, - void* sequenceProducerState, - ZSTD_sequenceProducer_F sequenceProducer + void* ZSTD_NULLABLE sequenceProducerState, + ZSTD_sequenceProducer_F ZSTD_NULLABLE sequenceProducer ); /*! ZSTD_CCtxParams_registerSequenceProducer() : @@ -2973,8 +3003,8 @@ ZSTD_registerSequenceProducer( ZSTDLIB_STATIC_API void ZSTD_CCtxParams_registerSequenceProducer( ZSTD_CCtx_params* params, - void* sequenceProducerState, - ZSTD_sequenceProducer_F sequenceProducer + void* ZSTD_NULLABLE sequenceProducerState, + ZSTD_sequenceProducer_F ZSTD_NULLABLE sequenceProducer ); @@ -3025,7 +3055,7 @@ ZSTD_CCtxParams_registerSequenceProducer( ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") -ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* ZSTD_NULLABLE dict, size_t dictSize, int compressionLevel); ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ @@ -3034,14 +3064,14 @@ ZSTDLIB_STATIC_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") -ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* ZSTD_NULLABLE dst, size_t dstCapacity, const void* ZSTD_NULLABLE src, size_t srcSize); ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") -ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* ZSTD_NULLABLE dst, size_t dstCapacity, const void* ZSTD_NULLABLE src, size_t srcSize); /* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */ ZSTD_DEPRECATED("use advanced API to access custom parameters") ZSTDLIB_STATIC_API -size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ +size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* ZSTD_NULLABLE dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ ZSTD_DEPRECATED("use advanced API to access custom parameters") ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ @@ -3132,7 +3162,7 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, si /* misc */ ZSTD_DEPRECATED("This function will likely be removed in the next minor release. It is misleading and has very limited utility.") ZSTDLIB_STATIC_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); -typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +typedef enum ZSTD_ENUM_CLOSED { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); @@ -3206,4 +3236,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* bloc } #endif +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull end +#endif + #endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ diff --git a/lib/zstd_annotations.h b/lib/zstd_annotations.h new file mode 100644 index 00000000000..2bdde3c0eff --- /dev/null +++ b/lib/zstd_annotations.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* + * Shared annotation infrastructure for zstd's public headers. + * + * Defines feature-check polyfills and the macros that decorate the public + * declarations with information used by Swift, clang's static analyser, and + * other tooling: + * + * ZSTD_NULLABILITY Switch (1/0). Default on for clang. Including + * code can `#define ZSTD_NULLABILITY 0` BEFORE the + * first inclusion of a zstd header to suppress all + * the nullability output below — this is what the + * legacy `libzstd` Swift umbrella does to preserve + * its pre-annotation surface. + * + * ZSTD_NULLABLE Expands to `_Nullable` when ZSTD_NULLABILITY is + * on, empty otherwise. Used in declarations to mark + * the specific pointers that genuinely accept NULL. + * The headers' API regions are wrapped in + * `#pragma clang assume_nonnull` so pointers + * without this marker default to non-null. + * + * ZSTD_ENUM_OPEN + * ZSTD_ENUM_CLOSED `__attribute__((enum_extensibility(...)))` for + * the modern Swift import — apply directly to the + * `typedef enum` tag. Gated on + * ZSTD_FOR_SWIFT_MODERN_API so the legacy libzstd + * module imports plain Int32 raw values. + * + * ZSTD_SWIFT_FIELD(n) `__attribute__((swift_name(n)))` for renaming a + * struct field as it appears in Swift. apinotes + * can rename functions / typedefs / tags but not + * fields, so this lives in the headers themselves. + * Gated on ZSTD_FOR_SWIFT_MODERN_API. + */ +#ifndef ZSTD_ANNOTATIONS_H +#define ZSTD_ANNOTATIONS_H + +/* `__has_feature` and `__has_attribute` are clang extensions. The C + * preprocessor doesn't short-circuit `defined(x) && x(...)` at parse + * time — unknown identifiers become `0`, so e.g. + * `__has_feature(nullability)` would become `0(nullability)` and fail + * to parse on GCC. The polyfills below make the macros safely expand + * to 0 on toolchains that don't define them. */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#ifndef ZSTD_NULLABILITY +# if __has_feature(nullability) +# define ZSTD_NULLABILITY 1 +# else +# define ZSTD_NULLABILITY 0 +# endif +#endif + +#if ZSTD_NULLABILITY +# define ZSTD_NULLABLE _Nullable + /* `_Nullable` is a clang language extension, so its mere presence + * trips `-Wnullability-extension` under `-Wpedantic`. The warning is + * not actionable for us — the whole point is to use the extension — + * so disable it for any TU that includes a zstd header. */ +# if defined(__clang__) +# pragma clang diagnostic ignored "-Wnullability-extension" +# endif +#else +# define ZSTD_NULLABLE +#endif + +#if defined(ZSTD_FOR_SWIFT_MODERN_API) && __has_attribute(enum_extensibility) +# define ZSTD_ENUM_OPEN __attribute__((enum_extensibility(open))) +# define ZSTD_ENUM_CLOSED __attribute__((enum_extensibility(closed))) +#else +# define ZSTD_ENUM_OPEN +# define ZSTD_ENUM_CLOSED +#endif + +#if defined(ZSTD_FOR_SWIFT_MODERN_API) && __has_attribute(swift_name) +# define ZSTD_SWIFT_FIELD(name) __attribute__((swift_name(name))) +#else +# define ZSTD_SWIFT_FIELD(name) +#endif + +#endif /* ZSTD_ANNOTATIONS_H */ diff --git a/lib/zstd_errors.h b/lib/zstd_errors.h index 8ebc95cbb2a..3123c396105 100644 --- a/lib/zstd_errors.h +++ b/lib/zstd_errors.h @@ -11,6 +11,12 @@ #ifndef ZSTD_ERRORS_H_398273423 #define ZSTD_ERRORS_H_398273423 +#include "zstd_annotations.h" + +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull begin +#endif + #if defined (__cplusplus) extern "C" { #endif @@ -57,7 +63,7 @@ extern "C" { * This is the only supported way to use the error list < v1.3.1 * note 3 : ZSTD_isError() is always correct, whatever the library version. **********************************************/ -typedef enum { +typedef enum ZSTD_ENUM_OPEN { ZSTD_error_no_error = 0, ZSTD_error_GENERIC = 1, ZSTD_error_prefix_unknown = 10, @@ -104,4 +110,8 @@ ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Sa } #endif +#if ZSTD_NULLABILITY +#pragma clang assume_nonnull end +#endif + #endif /* ZSTD_ERRORS_H_398273423 */