diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index a70ba478..b574ba7b 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -87,11 +87,21 @@ jobs: run: cargo nextest run --target ${{matrix.target}} ${{ matrix.features }} --no-fail-fast env: RUST_BACKTRACE: 1 + - name: cargo nextest cdylib + if: matrix.os != 'windows-2022' + working-directory: libz-rs-sys-cdylib + run: cargo llvm-cov nextest --target ${{matrix.target}} ${{ matrix.features }} --features="gz,__internal-test" --lcov --output-path cdylib.lcov.info --ignore-filename-regex "test-libz|dynamic-libz" + - name: cargo nextest cdylib + if: matrix.os == 'windows-2022' + working-directory: libz-rs-sys-cdylib + run: cargo nextest run --target ${{matrix.target}} ${{ matrix.features }} --features="gz,__internal-test" --no-fail-fast - name: Upload coverage to Codecov uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 if: matrix.os != 'windows-2022' && matrix.rust == 'stable' with: - files: ./lcov.info + files: | + ./lcov.info + ./cdylib.lcov.info fail_ci_if_error: false flags: test-${{matrix.target}} token: ${{ secrets.CODECOV_TOKEN }} @@ -167,15 +177,22 @@ jobs: uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 with: toolchain: stable - components: clippy + components: clippy, rustfmt targets: ${{matrix.target}} - name: Rust cache uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 with: shared-key: "stable-${{matrix.target}}" - - name: Run clippy - run: cargo clippy --target ${{matrix.target}} ${{matrix.features}} --workspace --all-targets -- -D warnings + - name: Run rustfmt and clippy + run: | + cargo fmt --all --check + cargo clippy --target ${{matrix.target}} ${{matrix.features}} --workspace --all-targets -- -D warnings + - name: Run rustfmt and clippy (cdylib) + working-directory: libz-rs-sys-cdylib + run: | + cargo fmt --all --check + cargo clippy --target ${{matrix.target}} ${{matrix.features}} --workspace --all-targets -- -D warnings - name: Run clippy (fuzzers) if: ${{ !contains(matrix.features, 'gz') }} run: cargo clippy --target ${{matrix.target}} ${{matrix.features}} --manifest-path ./fuzz/Cargo.toml --all-targets -- -D warnings @@ -255,7 +272,7 @@ jobs: done fuzz-code-coverage: - name: Fuzz with code coverage + name: Fuzz with code coverage runs-on: ubuntu-latest strategy: matrix: @@ -399,7 +416,7 @@ jobs: working-directory: libz-rs-sys-cdylib run: | # build using cargo-c this time - cargo cinstall --offline --release --destdir=/tmp/cargo-cbuild-libz-rs + cargo cinstall --release --destdir=/tmp/cargo-cbuild-libz-rs tree /tmp/cargo-cbuild-libz-rs # verify that the SONAME is set and includes a version objdump -p target/x86_64-unknown-linux-gnu/release/libz_rs.so | awk '/SONAME/{print $2}' | grep -E 'libz_rs\.so\.1' @@ -483,7 +500,8 @@ jobs: - name: Test allocator with miri run: "cargo +nightly miri nextest run -j4 -p zlib-rs --target ${{ matrix.target }} allocate::" - name: Test gz logic with miri - run: "cargo +nightly miri nextest run -j4 -p libz-rs-sys --target ${{ matrix.target }} --features=gz" + working-directory: libz-rs-sys-cdylib + run: "cargo +nightly miri nextest run -j4 -p libz-rs-sys-cdylib --target ${{ matrix.target }} --features=gz" env: MIRIFLAGS: "-Zmiri-tree-borrows -Zmiri-disable-isolation" diff --git a/Cargo.lock b/Cargo.lock index 158f6118..04839818 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,8 +132,16 @@ dependencies = [ [[package]] name = "libz-rs-sys" version = "0.5.0" +dependencies = [ + "zlib-rs", +] + +[[package]] +name = "libz-rs-sys-cdylib" +version = "0.5.0" dependencies = [ "libc", + "libz-rs-sys", "zlib-rs", ] @@ -280,6 +288,7 @@ dependencies = [ "libc", "libloading", "libz-rs-sys", + "libz-rs-sys-cdylib", "libz-sys", "quickcheck", "tempfile", diff --git a/libz-rs-sys-cdylib/Cargo.lock b/libz-rs-sys-cdylib/Cargo.lock index 30a537f2..79e94b7d 100644 --- a/libz-rs-sys-cdylib/Cargo.lock +++ b/libz-rs-sys-cdylib/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + [[package]] name = "libz-rs-sys" version = "0.5.0" @@ -13,7 +19,9 @@ dependencies = [ name = "libz-rs-sys-cdylib" version = "0.5.0" dependencies = [ + "libc", "libz-rs-sys", + "zlib-rs", ] [[package]] diff --git a/libz-rs-sys-cdylib/Cargo.toml b/libz-rs-sys-cdylib/Cargo.toml index e3df2cdf..b55ce489 100644 --- a/libz-rs-sys-cdylib/Cargo.toml +++ b/libz-rs-sys-cdylib/Cargo.toml @@ -12,8 +12,7 @@ rust-version = "1.75" # MSRV [lib] name = "z_rs" # turns into e.g. `libz_rs.so` -crate-type=["cdylib"] -test = false +crate-type = ["cdylib", "lib"] [profile.dev] panic = "abort" # abort on panics. This is crucial, unwinding would cause UB! @@ -28,9 +27,13 @@ rust-allocator = ["libz-rs-sys/rust-allocator", "libz-rs-sys/std"] # by default, custom-prefix = ["libz-rs-sys/custom-prefix"] # use the LIBZ_RS_SYS_PREFIX to prefix all exported symbols semver-prefix = ["libz-rs-sys/semver-prefix"] # prefix all symbols in a semver-compatible way capi = [] +gz = ["dep:libc"] # support for the `gz*` functions is experimental +__internal-test = [] [dependencies] libz-rs-sys = { version = "0.5.0", path = "../libz-rs-sys", default-features = false, features = ["export-symbols"] } +zlib-rs = { version = "0.5.0", path = "../zlib-rs", default-features = false } +libc = { version = "0.2.171", optional = true } [package.metadata.capi.library] version = "1.3.0" # the zlib api version we match diff --git a/libz-rs-sys/src/gz.rs b/libz-rs-sys-cdylib/src/gz.rs similarity index 97% rename from libz-rs-sys/src/gz.rs rename to libz-rs-sys-cdylib/src/gz.rs index 5be94045..22d46547 100644 --- a/libz-rs-sys/src/gz.rs +++ b/libz-rs-sys-cdylib/src/gz.rs @@ -5,8 +5,8 @@ pub use zlib_rs::c_api::*; use crate::gz::GzMode::GZ_READ; use crate::{ - deflate, deflateEnd, deflateInit2_, deflateReset, inflate, inflateEnd, inflateInit2, - inflateReset, z_off_t, zlibVersion, + deflate, deflateEnd, deflateInit2_, deflateReset, inflate, inflateEnd, inflateInit2_, + inflateReset, z_off_t, z_stream, zlibVersion, }; use core::ffi::{c_char, c_int, c_uint, c_void, CStr}; use core::ptr; @@ -22,9 +22,11 @@ use zlib_rs::MAX_WBITS; /// of an open gzFile to support the gzgetc() C macro. Since Rust code won't be /// using that C macro, we define gzFile_s as an empty structure. The first fields /// in GzState match what would be in the C version of gzFile_s. +#[allow(non_camel_case_types)] pub enum gzFile_s {} /// File handle for an open gzip file. +#[allow(non_camel_case_types)] pub type gzFile = *mut gzFile_s; // The internals of a gzip file handle (the thing gzFile actually points to, with the @@ -139,6 +141,7 @@ impl GzState { // Gzip operating modes // NOTE: These values match what zlib-ng uses. +#[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum GzMode { GZ_NONE = 0, @@ -186,7 +189,9 @@ enum Source { /// /// The caller must ensure that `path` and `mode` point to valid C strings. If the /// return value is non-NULL, caller must delete it using only [`gzclose`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzopen))] +/// +/// [`gzfree`]: crate::z_stream +#[export_name = crate::prefix!(gzopen)] pub unsafe extern "C-unwind" fn gzopen(path: *const c_char, mode: *const c_char) -> gzFile { if path.is_null() { return ptr::null_mut(); @@ -208,7 +213,9 @@ pub unsafe extern "C-unwind" fn gzopen(path: *const c_char, mode: *const c_char) /// /// The caller must ensure that `mode` points to a valid C string. If the /// return value is non-NULL, caller must delete it using only [`gzclose`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzdopen))] +/// +/// [`gzfree`]: crate::z_stream +#[export_name = crate::prefix!(gzdopen)] pub unsafe extern "C-unwind" fn gzdopen(fd: c_int, mode: *const c_char) -> gzFile { // Safety: the caller is responsible for `mode` being a non-null C string. unsafe { gzopen_help(Source::Fd(fd), mode) } @@ -360,9 +367,6 @@ fn fd_path(buf: &mut [u8; 27], fd: c_int) -> &CStr { // characters, plus space for the largest decimal value for the `c_int` type. On some systems // the c_int type can actually be 64 bits. The `i64::MIN` value has 20 digits, and the minus // sign, for a total of 6 + 20 + 1 = 27. - #[cfg(feature = "std")] - debug_assert!(format!("\0", i64::MIN).len() <= buf.len()); - struct Writer<'a> { buf: &'a mut [u8; 27], len: usize, @@ -551,7 +555,7 @@ unsafe fn deallocate_cstr(s: *mut c_char) { /// /// `file` must not be used after this call returns, as the memory it references may have /// been deallocated. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzclose))] +#[export_name = crate::prefix!(gzclose)] pub unsafe extern "C-unwind" fn gzclose(file: gzFile) -> c_int { let Some(state) = (unsafe { file.cast::().as_ref() }) else { return Z_STREAM_ERROR; @@ -578,7 +582,7 @@ pub unsafe extern "C-unwind" fn gzclose(file: gzFile) -> c_int { /// /// `file` must not be used after this call returns, as the memory it references may have /// been deallocated. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzclose_r))] +#[export_name = crate::prefix!(gzclose_r)] pub unsafe extern "C-unwind" fn gzclose_r(file: gzFile) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return Z_STREAM_ERROR; @@ -627,7 +631,7 @@ pub unsafe extern "C-unwind" fn gzclose_r(file: gzFile) -> c_int { /// /// `file` must not be used after this call returns, as the memory it references may have /// been deallocated. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzclose_w))] +#[export_name = crate::prefix!(gzclose_w)] pub unsafe extern "C-unwind" fn gzclose_w(file: gzFile) -> c_int { let mut ret = Z_OK; @@ -689,7 +693,7 @@ pub unsafe extern "C-unwind" fn gzclose_w(file: gzFile) -> c_int { /// `file` must be one of the following: /// - A file handle must have been obtained from a function in this library, such as [`gzopen`]. /// - A null pointer. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzbuffer))] +#[export_name = crate::prefix!(gzbuffer)] pub unsafe extern "C-unwind" fn gzbuffer(file: gzFile, size: c_uint) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -748,7 +752,7 @@ pub unsafe extern "C-unwind" fn gzbuffer(file: gzFile, size: c_uint) -> c_int { /// deallocate the string. /// /// If `errnum` is non-null, it must point to an address at which a [`c_int`] may be written. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzerror))] +#[export_name = crate::prefix!(gzerror)] pub unsafe extern "C-unwind" fn gzerror(file: gzFile, errnum: *mut c_int) -> *const c_char { // Get internal structure and check integrity let Some(state) = (unsafe { file.cast::().as_ref() }) else { @@ -784,7 +788,7 @@ pub unsafe extern "C-unwind" fn gzerror(file: gzFile, errnum: *mut c_int) -> *co /// # Safety /// /// `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzclearerr))] +#[export_name = crate::prefix!(gzclearerr)] pub unsafe extern "C-unwind" fn gzclearerr(file: gzFile) { // Get internal structure and check integrity let Some(state) = (unsafe { file.cast::().as_mut() }) else { @@ -821,7 +825,7 @@ pub unsafe extern "C-unwind" fn gzclearerr(file: gzFile) { /// # Safety /// /// `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzeof))] +#[export_name = crate::prefix!(gzeof)] pub unsafe extern "C-unwind" fn gzeof(file: gzFile) -> c_int { // Get internal structure and check integrity let Some(state) = (unsafe { file.cast::().as_ref() }) else { @@ -861,7 +865,7 @@ pub unsafe extern "C-unwind" fn gzeof(file: gzFile) -> c_int { /// # Safety /// /// `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzdirect))] +#[export_name = crate::prefix!(gzdirect)] pub unsafe extern "C-unwind" fn gzdirect(file: gzFile) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return 0; @@ -920,7 +924,7 @@ pub unsafe extern "C-unwind" fn gzdirect(file: gzFile) -> c_int { /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. /// - The caller must ensure that `buf` points to at least `len` writable bytes. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzread))] +#[export_name = crate::prefix!(gzread)] pub unsafe extern "C-unwind" fn gzread(file: gzFile, buf: *mut c_void, len: c_uint) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -980,7 +984,7 @@ pub unsafe extern "C-unwind" fn gzread(file: gzFile, buf: *mut c_void, len: c_ui /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. /// - The caller must ensure that `buf` points to at least `size * nitems` writable bytes. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzfread))] +#[export_name = crate::prefix!(gzfread)] pub unsafe extern "C-unwind" fn gzfread( buf: *mut c_void, size: size_t, @@ -1207,7 +1211,15 @@ unsafe fn gz_look(state: &mut GzState) -> Result<(), ()> { state.stream.next_in = ptr::null_mut(); // Safety: `gzopen_help` initialized `state.stream`'s `zalloc`, `zfree`, and // `opaque` fields as needed by `inflateInit2`. - if unsafe { inflateInit2(&mut state.stream as *mut z_stream, MAX_WBITS + 16) } != Z_OK { + if unsafe { + inflateInit2_( + &mut state.stream as *mut z_stream, + MAX_WBITS + 16, + zlibVersion(), + std::mem::size_of::() as i32, + ) + } != Z_OK + { // Safety: The caller confirmed the validity of `state`, and `free_buffers` checks // for null input and output pointers internally. unsafe { free_buffers(state) }; @@ -1478,7 +1490,7 @@ unsafe fn gz_decomp(state: &mut GzState) -> Result<(), ()> { /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. /// - `buf` must point to at least `len` bytes of readable memory. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzwrite))] +#[export_name = crate::prefix!(gzwrite)] pub unsafe extern "C-unwind" fn gzwrite(file: gzFile, buf: *const c_void, len: c_uint) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return 0; @@ -1527,7 +1539,7 @@ pub unsafe extern "C-unwind" fn gzwrite(file: gzFile, buf: *const c_void, len: c /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. /// - The caller must ensure that `buf` points to at least `size * nitems` readable bytes. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzfwrite))] +#[export_name = crate::prefix!(gzfwrite)] pub unsafe extern "C-unwind" fn gzfwrite( buf: *const c_void, size: size_t, @@ -1863,7 +1875,7 @@ fn gz_comp(state: &mut GzState, flush: c_int) -> Result<(), ()> { /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzflush))] +#[export_name = crate::prefix!(gzflush)] pub unsafe extern "C-unwind" fn gzflush(file: gzFile, flush: c_int) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return Z_STREAM_ERROR; @@ -1906,7 +1918,7 @@ pub unsafe extern "C-unwind" fn gzflush(file: gzFile, flush: c_int) -> c_int { /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gztell))] +#[export_name = crate::prefix!(gztell)] pub unsafe extern "C-unwind" fn gztell(file: gzFile) -> z_off_t { let Some(state) = (unsafe { file.cast::().as_ref() }) else { return -1; @@ -1940,7 +1952,7 @@ pub unsafe extern "C-unwind" fn gztell(file: gzFile) -> z_off_t { /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzoffset))] +#[export_name = crate::prefix!(gzoffset)] pub unsafe extern "C-unwind" fn gzoffset(file: gzFile) -> z_off_t { let Some(state) = (unsafe { file.cast::().as_ref() }) else { return -1; @@ -1975,7 +1987,7 @@ pub unsafe extern "C-unwind" fn gzoffset(file: gzFile) -> z_off_t { /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzputc))] +#[export_name = crate::prefix!(gzputc)] pub unsafe extern "C-unwind" fn gzputc(file: gzFile, c: c_int) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -2033,7 +2045,7 @@ pub unsafe extern "C-unwind" fn gzputc(file: gzFile, c: c_int) -> c_int { /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. /// - `s` must point to a null-terminated C string. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzputs))] +#[export_name = crate::prefix!(gzputs)] pub unsafe extern "C-unwind" fn gzputs(file: gzFile, s: *const c_char) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -2075,7 +2087,7 @@ pub unsafe extern "C-unwind" fn gzputs(file: gzFile, s: *const c_char) -> c_int /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzgetc))] +#[export_name = crate::prefix!(gzgetc)] pub unsafe extern "C-unwind" fn gzgetc(file: gzFile) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -2119,7 +2131,7 @@ pub unsafe extern "C-unwind" fn gzgetc(file: gzFile) -> c_int { /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzgetc_))] +#[export_name = crate::prefix!(gzgetc_)] pub unsafe extern "C-unwind" fn gzgetc_(file: gzFile) -> c_int { // Safety: The caller has ensured that `file` is null or a valid file handle. unsafe { gzgetc(file) } @@ -2143,7 +2155,7 @@ pub unsafe extern "C-unwind" fn gzgetc_(file: gzFile) -> c_int { /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzungetc))] +#[export_name = crate::prefix!(gzungetc)] pub unsafe extern "C-unwind" fn gzungetc(c: c_int, file: gzFile) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -2252,7 +2264,7 @@ pub unsafe extern "C-unwind" fn gzungetc(c: c_int, file: gzFile) -> c_int { /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. /// - `buf` must be null or a pointer to at least `len` writable bytes. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzgets))] +#[export_name = crate::prefix!(gzgets)] pub unsafe extern "C-unwind" fn gzgets(file: gzFile, buf: *mut c_char, len: c_int) -> *mut c_char { // Check parameters. if buf.is_null() || len < 1 { @@ -2346,7 +2358,7 @@ pub unsafe extern "C-unwind" fn gzgets(file: gzFile, buf: *mut c_char, len: c_in } /// Dynamically update the compression level and strategy for `file`. See the -/// description of [`deflateInit2`] for the meaning of these parameters. Previously +/// description of [`deflateInit2_`] for the meaning of these parameters. Previously /// provided data is flushed before applying the parameter changes. /// /// Note: If `level` is not valid, this function will silently fail with a return @@ -2363,7 +2375,7 @@ pub unsafe extern "C-unwind" fn gzgets(file: gzFile, buf: *mut c_char, len: c_in /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzsetparams))] +#[export_name = crate::prefix!(gzsetparams)] pub unsafe extern "C-unwind" fn gzsetparams(file: gzFile, level: c_int, strategy: c_int) -> c_int { let Ok(strategy) = Strategy::try_from(strategy) else { return Z_STREAM_ERROR; @@ -2433,7 +2445,7 @@ pub unsafe extern "C-unwind" fn gzsetparams(file: gzFile, level: c_int, strategy /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzseek))] +#[export_name = crate::prefix!(gzseek)] pub unsafe extern "C-unwind" fn gzseek(file: gzFile, offset: z_off_t, whence: c_int) -> z_off_t { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; @@ -2540,7 +2552,7 @@ pub unsafe extern "C-unwind" fn gzseek(file: gzFile, offset: z_off_t, whence: c_ /// # Safety /// /// - `file`, if non-null, must be an open file handle obtained from [`gzopen`] or [`gzdopen`]. -#[cfg_attr(feature = "export-symbols", export_name = crate::prefix!(gzrewind))] +#[export_name = crate::prefix!(gzrewind)] pub unsafe extern "C-unwind" fn gzrewind(file: gzFile) -> c_int { let Some(state) = (unsafe { file.cast::().as_mut() }) else { return -1; diff --git a/libz-rs-sys-cdylib/src/lib.rs b/libz-rs-sys-cdylib/src/lib.rs index 73629974..f74e2e56 100644 --- a/libz-rs-sys-cdylib/src/lib.rs +++ b/libz-rs-sys-cdylib/src/lib.rs @@ -2,5 +2,59 @@ extern crate libz_rs_sys; pub use libz_rs_sys::*; -#[cfg(not(panic = "abort"))] +#[cfg(not(any(panic = "abort", feature = "__internal-test", test, doc, miri)))] compile_error!("panic=\"abort\" is mandatory because unwinding to C is undefined behavior"); + +#[cfg(feature = "gz")] +mod gz; + +#[cfg(feature = "gz")] +pub use gz::*; + +#[cfg(feature = "gz")] +#[allow(unused)] +mod custom_prefix { + #[cfg(feature = "custom-prefix")] + macro_rules! prefix { + ($name:expr) => { + concat!(env!("LIBZ_RS_SYS_PREFIX"), stringify!($name)) + }; + } + + // NOTE: once we reach 1.0.0, the macro used for the `semver-prefix` feature should no longer include the + // minor version in the name. The name is meant to be unique between semver-compatible versions! + const _PRE_ONE_DOT_O: () = assert!(env!("CARGO_PKG_VERSION_MAJOR").as_bytes()[0] == b'0'); + + #[cfg(feature = "semver-prefix")] + macro_rules! prefix { + ($name:expr) => { + concat!( + "LIBZ_RS_SYS_v", + env!("CARGO_PKG_VERSION_MAJOR"), + "_", + env!("CARGO_PKG_VERSION_MINOR"), + "_x_", + stringify!($name) + ) + }; + } + + #[cfg(all(not(feature = "custom-prefix"), not(feature = "semver-prefix"),))] + macro_rules! prefix { + ($name:expr) => { + stringify!($name) + }; + } + + #[cfg(all(not(feature = "custom-prefix"), not(feature = "semver-prefix"), test))] + macro_rules! prefix { + ($name:expr) => { + concat!("LIBZ_RS_SYS_TEST_", stringify!($name)) + }; + } + + pub(crate) use prefix; +} + +#[cfg(feature = "gz")] +pub(crate) use custom_prefix::prefix; diff --git a/libz-rs-sys/src/test-data/example.gz b/libz-rs-sys-cdylib/src/test-data/example.gz similarity index 100% rename from libz-rs-sys/src/test-data/example.gz rename to libz-rs-sys-cdylib/src/test-data/example.gz diff --git a/libz-rs-sys/src/test-data/example.txt b/libz-rs-sys-cdylib/src/test-data/example.txt similarity index 100% rename from libz-rs-sys/src/test-data/example.txt rename to libz-rs-sys-cdylib/src/test-data/example.txt diff --git a/libz-rs-sys/src/test-data/incomplete-magic.gz b/libz-rs-sys-cdylib/src/test-data/incomplete-magic.gz similarity index 100% rename from libz-rs-sys/src/test-data/incomplete-magic.gz rename to libz-rs-sys-cdylib/src/test-data/incomplete-magic.gz diff --git a/libz-rs-sys/src/test-data/magic-only.gz b/libz-rs-sys-cdylib/src/test-data/magic-only.gz similarity index 100% rename from libz-rs-sys/src/test-data/magic-only.gz rename to libz-rs-sys-cdylib/src/test-data/magic-only.gz diff --git a/libz-rs-sys/Cargo.toml b/libz-rs-sys/Cargo.toml index 1e5fc6a1..0b14e6d6 100644 --- a/libz-rs-sys/Cargo.toml +++ b/libz-rs-sys/Cargo.toml @@ -19,8 +19,6 @@ export-symbols = [] # whether the zlib api symbols are publicly exported custom-prefix = ["export-symbols"] # use the LIBZ_RS_SYS_PREFIX to prefix all exported symbols testing-prefix = ["export-symbols"] # prefix all symbols with LIBZ_RS_SYS_TEST_ for testing semver-prefix = ["export-symbols"] # prefix all symbols in a semver-compatible way -gz = ["dep:libc"] # gzip support has to be configured explicitly, to avoid a libc dependency in the core zlib-rs [dependencies] zlib-rs = { workspace = true, default-features = false } -libc = { version = "0.2.171", optional = true } diff --git a/libz-rs-sys/src/lib.rs b/libz-rs-sys/src/lib.rs index b46fc359..44ba6f2d 100644 --- a/libz-rs-sys/src/lib.rs +++ b/libz-rs-sys/src/lib.rs @@ -37,12 +37,6 @@ use zlib_rs::{ pub use zlib_rs::c_api::*; -#[cfg(feature = "gz")] -mod gz; - -#[cfg(feature = "gz")] -pub use gz::*; - #[cfg(feature = "custom-prefix")] macro_rules! prefix { ($name:expr) => { @@ -60,9 +54,9 @@ macro_rules! prefix { concat!( "LIBZ_RS_SYS_v", env!("CARGO_PKG_VERSION_MAJOR"), - ".", + "_", env!("CARGO_PKG_VERSION_MINOR"), - ".x_", + "_x_", stringify!($name) ) }; diff --git a/test-libz-rs-sys/Cargo.toml b/test-libz-rs-sys/Cargo.toml index 6a55e566..7ac2f004 100644 --- a/test-libz-rs-sys/Cargo.toml +++ b/test-libz-rs-sys/Cargo.toml @@ -13,13 +13,14 @@ rust-version.workspace = true [features] default = ["rust-allocator", "gz"] -c-allocator = ["libz-rs-sys/c-allocator"] -rust-allocator = ["libz-rs-sys/rust-allocator"] -gz = ["libz-rs-sys/gz", "dep:libc"] +c-allocator = ["libz-rs-sys/c-allocator", "libz-rs-sys-cdylib/c-allocator"] +rust-allocator = ["libz-rs-sys/rust-allocator", "libz-rs-sys-cdylib/rust-allocator"] +gz = ["libz-rs-sys-cdylib/gz", "dep:libc"] [dependencies] zlib-rs = { workspace = true, default-features = false, features = ["std", "c-allocator", "rust-allocator", "__internal-test"] } libz-rs-sys = { workspace = true, default-features = false, features = ["std", "testing-prefix"] } +libz-rs-sys-cdylib = { path = "../libz-rs-sys-cdylib", default-features = false, features = ["semver-prefix", "__internal-test"] } libz-sys.workspace = true libc = { version = "0.2.171", optional = true } diff --git a/test-libz-rs-sys/src/gz.rs b/test-libz-rs-sys/src/gz.rs index d8f6ad77..a3fc1262 100644 --- a/test-libz-rs-sys/src/gz.rs +++ b/test-libz-rs-sys/src/gz.rs @@ -1,6 +1,6 @@ use zlib_rs::c_api::*; -use libz_rs_sys::{ +use z_rs::{ gzFile_s, gzbuffer, gzclearerr, gzclose, gzclose_r, gzclose_w, gzdirect, gzdopen, gzerror, gzflush, gzfread, gzfwrite, gzgetc, gzgetc_, gzgets, gzoffset, gzopen, gzputc, gzputs, gzread, gzrewind, gzseek, gzsetparams, gztell, gzungetc, gzwrite,