Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,30 +64,30 @@ jobs:
cp Cargo.lock.msrv Cargo.lock
- run: |
cargo test
cargo clean -p liblzma -p liblzma-sys
cargo clean -p xz -p liblzma-sys
- run: |
cargo test --features parallel
cargo clean -p liblzma -p liblzma-sys
cargo clean -p xz -p liblzma-sys
- run: |
cargo test --no-default-features --features xz-sys
cargo clean -p liblzma -p xz-sys
cargo clean -p xz -p xz-sys
- run: |
cargo test --no-default-features --features liblzma-sys
cargo clean -p liblzma -p liblzma-sys
cargo clean -p xz -p liblzma-sys
# thin-lto and fat-lto feature required use clang as a linker, but linux default linker is gcc. so exclude thin-lto and fat-lto.
- run: |
cargo test --no-default-features --features liblzma-sys,parallel,static
cargo clean -p liblzma -p liblzma-sys
cargo clean -p xz -p liblzma-sys
if: ${{ startsWith(matrix.os, 'ubuntu') }}
- run: |
cargo test --test sys_equivalence
cargo clean -p liblzma -p liblzma-sys
cargo clean -p xz -p liblzma-sys
if: ${{ !startsWith(matrix.os, 'ubuntu') }}
- run: |
cargo run --manifest-path systest/Cargo.toml --no-default-features --features xz-sys
cargo clean -p xz-sys
cargo run --manifest-path systest/Cargo.toml --no-default-features --features liblzma-sys
cargo clean -p liblzma -p liblzma-sys
cargo clean -p xz -p liblzma-sys
if: matrix.static == 'yes'
- run: cargo run --manifest-path systest/Cargo.toml --no-default-features --features liblzma-sys,bindgen
if: matrix.static == 'yes'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ jobs:
working-directory: liblzma-sys
env:
CARGO_REGISTRY_TOKEN: "${{ secrets.CRATES_IO_API_KEY }}"
- if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && startsWith(github.ref, 'refs/tags/liblzma')"
name: Publish liblzma crate
- if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && !startsWith(github.ref, 'refs/tags/xz-sys') && startsWith(github.ref, 'refs/tags/xz')"
name: Publish xz crate
Comment on lines +23 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Tag condition leaks to xz-core (and any future xz* crate).

startsWith(github.ref, 'refs/tags/xz') matches refs/tags/xz-core-* (and e.g. xz-foo-*). Only xz-sys is explicitly excluded, so pushing an xz-core tag would erroneously trigger publication of the root xz crate from this step. Either exclude xz-core as well, or tighten the prefix to match only the root crate's tag scheme (e.g. xz-v / xz@).

🔧 Proposed fix (exclude xz-core explicitly)
-      - if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && !startsWith(github.ref, 'refs/tags/xz-sys') && startsWith(github.ref, 'refs/tags/xz')"
+      - if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && !startsWith(github.ref, 'refs/tags/xz-sys') && !startsWith(github.ref, 'refs/tags/xz-core') && startsWith(github.ref, 'refs/tags/xz')"
         name: Publish xz crate

Alternatively, lock the prefix to an unambiguous root-crate tag pattern:

-      - if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && !startsWith(github.ref, 'refs/tags/xz-sys') && startsWith(github.ref, 'refs/tags/xz')"
+      - if: "startsWith(github.ref, 'refs/tags/xz-v')"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && !startsWith(github.ref, 'refs/tags/xz-sys') && startsWith(github.ref, 'refs/tags/xz')"
name: Publish xz crate
- if: "!startsWith(github.ref, 'refs/tags/liblzma-sys') && !startsWith(github.ref, 'refs/tags/xz-sys') && !startsWith(github.ref, 'refs/tags/xz-core') && startsWith(github.ref, 'refs/tags/xz')"
name: Publish xz crate
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish.yml around lines 23 - 24, The tag condition for
the "Publish xz crate" step is too broad (startsWith(github.ref,
'refs/tags/xz')) and will match tags like refs/tags/xz-core-*, causing wrong
publishes; update the if condition around the step that references github.ref
and startsWith to either explicitly exclude xz-core (add &&
!startsWith(github.ref, 'refs/tags/xz-core')) or tighten the match to the root
crate tag pattern (e.g., use a stricter startsWith like 'refs/tags/xz-' combined
with a version marker or use a delimiter such as 'refs/tags/xz@' or
'refs/tags/xz-v' to only match the intended root xz tags).

run: cargo publish
working-directory: .
env:
Expand Down
34 changes: 17 additions & 17 deletions Cargo.lock.msrv

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[package]
name = "liblzma"
name = "xz"
version = "0.4.6"
authors = ["Alex Crichton <alex@alexcrichton.com>", "Portable-Network-Archive Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
keywords = ["lzma", "xz", "encoding", "wasm"]
repository = "https://github.com/portable-network-archive/liblzma-rs"
homepage = "https://github.com/portable-network-archive/liblzma-rs"
repository = "https://github.com/youknowone/xz-rs"
homepage = "https://github.com/youknowone/xz-rs"
description = """
Rust bindings to liblzma providing Read/Write streams as well as low-level
Pure Rust xz library providing Read/Write streams as well as low-level
in-memory encoding/decoding. forked from xz2.
"""
categories = ["compression", "api-bindings"]
Expand Down Expand Up @@ -41,8 +41,8 @@ required-features = ["bench"]
getrandom = { version = "0.2", features = ["js"] }

[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
xz-sys = { path = "xz-sys" }
liblzma-sys = { path = "liblzma-sys" }
xz-sys = { path = "xz-sys", features = ["parallel"] }
liblzma-sys = { path = "liblzma-sys", features = ["parallel"] }

[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dev-dependencies]
wasm-bindgen-test = "0.3"
Expand Down
43 changes: 28 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# liblzma
# xz

[![CI](https://github.com/Portable-Network-Archive/liblzma-rs/actions/workflows/main.yml/badge.svg)](https://github.com/Portable-Network-Archive/liblzma-rs/actions/workflows/main.yml)
[![CI](https://github.com/youknowone/xz-rs/actions/workflows/main.yml/badge.svg)](https://github.com/youknowone/xz-rs/actions/workflows/main.yml)
[![Crates.io][crates-badge]][crates-url]

[crates-badge]: https://img.shields.io/crates/v/liblzma.svg
[crates-url]: https://crates.io/crates/liblzma
[crates-badge]: https://img.shields.io/crates/v/xz.svg
[crates-url]: https://crates.io/crates/xz

[Documentation](https://docs.rs/liblzma)
[Documentation](https://docs.rs/xz)

Bindings to the liblzma implementation in Rust, also provides types to
read/write xz streams.
Pure Rust xz2/liblzma-compatible crates for reading and writing xz streams.

**This crate is forked from [xz2](https://crates.io/crates/xz2) and `liblzma = "0.1.x"` is fully compatible with `xz2 = "0.1.7"`,**
**This crate is forked from [xz2](https://crates.io/crates/xz2) and `xz = "0.1.x"` is fully compatible with `xz2 = "0.1.7"`,**
so you can migrate simply.

## Migrate from xz2
Expand All @@ -20,13 +19,13 @@ so you can migrate simply.
# Cargo.toml
[dependencies]
-xz2 = "0.1.7"
+liblzma = "0.1.7"
+xz = "0.1.7"
```

```diff
// *.rs
-use xz2;
+use liblzma;
+use xz;
```

## Version 0.2.x breaking changes
Expand All @@ -45,14 +44,28 @@ so you can migrate simply.
- XZ upgraded to 5.8
- Dropped `tokio` support (If you need async I/O, use [`async-compression`](https://github.com/Nullus157/async-compression) crate with `lzma` feature flag)

## Backend selection
## Crates and backend selection

The default build uses the pure Rust backend via `xz-sys`.
This repository contains three pure Rust crates:

Use the original C backend only when you explicitly opt into it:
- `xz-core` is a direct port of the xz C library internals.
- `xz-sys` is a C ABI compatibility layer backed by `xz-core`. It is intended
to be compatible with `xz2-sys` and `liblzma-sys`, and should be easy to link
from C as a liblzma-compatible library.
- `xz` is the high-level Rust interface intended as a replacement for `xz2`
and `liblzma`.

The high-level `xz` crate defaults to the pure Rust `xz-core` backend. You can
disable default features and choose exactly one backend explicitly:

- `xz-core` calls the pure Rust core directly.
- `xz-sys` calls the pure Rust core through the liblzma-compatible C ABI layer.
- `liblzma-sys` calls the original C liblzma implementation.

To use the original C backend:

```toml
liblzma = { version = "0.4", default-features = false, features = ["liblzma-sys"] }
xz = { version = "0.4", default-features = false, features = ["liblzma-sys"] }
```

## License
Expand All @@ -69,5 +82,5 @@ at your option.
### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in liblzma by you, as defined in the Apache-2.0 license, shall be
for inclusion in xz by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
10 changes: 6 additions & 4 deletions docs/performance-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ This repository now has a repeatable loop for backend comparison, profiling, and

Important: the C and Rust sys backends must never be linked into the same process when comparing performance. Both export the same `lzma_*` symbols, so shared-process comparisons can silently resolve to the wrong implementation.

The root crate now has three backend modes:
The root crate has three backend modes:

- `xz-core`: direct Rust ABI calls into the pure Rust port
- `xz-core`: direct Rust ABI calls into the pure Rust port. This is the default.
- `xz-sys`: C ABI calls into the pure Rust port through the `xz-sys` shell
- `liblzma-sys`: C ABI calls into vendored C `liblzma`

Expand All @@ -24,6 +24,8 @@ cargo test
cargo test --no-default-features --features xz-sys
cargo test --no-default-features --features liblzma-sys
cargo test --test sys_equivalence
cargo run --manifest-path systest/Cargo.toml --no-default-features --features xz-sys
cargo run --manifest-path systest/Cargo.toml --no-default-features --features liblzma-sys
```

## 2. Compare the full test suite
Expand Down Expand Up @@ -80,7 +82,7 @@ still needs millions of in-process iterations; start around `--iters 2000000 --w
comparison scripts also pre-generate its compressed input so the one-time encode setup
doesn't hide the `uncompressed_size()` path.

There is still a criterion bench in [`benches/backend_comparison.rs`](../benches/backend_comparison.rs), but it now measures one backend per run. Use it only with exactly one backend feature enabled.
There is still a criterion bench in [`benches/backend_comparison.rs`](../benches/backend_comparison.rs), but it now measures one backend per run. Use it with exactly one backend feature enabled.

For high-level API regressions, compare the root crate against the upstream XZ corpus:

Expand All @@ -92,7 +94,7 @@ scripts/compare_api_workloads.sh qc --mode both --cases 128 --max-size 4096 --it
scripts/compare_api_workloads.sh bufread-trailing --mode both --input-size 1024 --trailing-size 123 --iters 1000 --warmup 100
```

This uses [`examples/standard_files_probe.rs`](../examples/standard_files_probe.rs), which mirrors the `tests/xz.rs` `standard_files` path and writes reports to:
This uses [`examples/standard_files_probe.rs`](../examples/standard_files_probe.rs), which mirrors the `tests/standard_files.rs` `standard_files` path and writes reports to:

- `target/perf-results/api-standard-files.json`
- `target/perf-results/api-standard-files.md`
Expand Down
2 changes: 1 addition & 1 deletion examples/bufread_trailing_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::env;
use std::io::Read;
use std::time::{Duration, Instant};

use liblzma::bufread;
use xz::bufread;

#[cfg(feature = "xz-core")]
const BACKEND_NAME: &str = "xz-core";
Expand Down
4 changes: 2 additions & 2 deletions examples/qc_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::env;
use std::io::{Read, Write};
use std::time::{Duration, Instant};

use liblzma::read;
use liblzma::write;
use xz::read;
use xz::write;

#[cfg(feature = "xz-core")]
const BACKEND_NAME: &str = "xz-core";
Expand Down
6 changes: 3 additions & 3 deletions examples/standard_files_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use std::io::{Read, Write};
use std::path::PathBuf;
use std::time::{Duration, Instant};

use liblzma::read;
use liblzma::stream;
use liblzma::write;
use xz::read;
use xz::stream;
use xz::write;

#[cfg(feature = "xz-core")]
const BACKEND_NAME: &str = "xz-core";
Expand Down
2 changes: 1 addition & 1 deletion scripts/compare_all_trimmed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ record_pair() {

echo "prebuilding root test binaries..."
env CARGO_TARGET_DIR="$RUST_TARGET" \
cargo test -p liblzma --release --no-default-features --features xz-core --lib --tests --no-run >/dev/null
cargo test -p xz --release --no-default-features --features xz-core --lib --tests --no-run >/dev/null
env LZMA_API_STATIC=1 CARGO_TARGET_DIR="$C_TARGET" \
cargo test --release --no-default-features --features liblzma-sys --lib --tests --no-run >/dev/null

Expand Down
2 changes: 1 addition & 1 deletion scripts/compare_backends.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ SYSTEST_RUST_CMD="env CARGO_TARGET_DIR=$SYSTEST_RUST_TARGET cargo test -p systes
SYSTEST_C_CMD="env LZMA_API_STATIC=1 CARGO_TARGET_DIR=$SYSTEST_C_TARGET cargo test -p systest --release --no-default-features --features liblzma-sys -- --test-threads=1"

echo "prebuilding root test binaries..."
env CARGO_TARGET_DIR="$ROOT_RUST_TARGET" cargo test -p liblzma --release --no-default-features --features xz-core --no-run >/dev/null
env CARGO_TARGET_DIR="$ROOT_RUST_TARGET" cargo test -p xz --release --no-default-features --features xz-core --no-run >/dev/null
env LZMA_API_STATIC=1 CARGO_TARGET_DIR="$ROOT_C_TARGET" cargo test --release --no-default-features --features liblzma-sys --no-run >/dev/null

hyperfine \
Expand Down
2 changes: 1 addition & 1 deletion scripts/inspect_codegen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ print_usage() {
Usage: scripts/inspect_codegen.sh <symbol> [options]

Options:
--package <name> Cargo package to inspect (default: xz)
--package <name> Cargo package to inspect (default: xz-core)
--format <asm|llvm|mir> Output format for cargo-asm (default: asm)
--features <list> Cargo feature list passed to cargo-asm
--target-dir <dir> Cargo target dir (default: target/codegen)
Expand Down
6 changes: 3 additions & 3 deletions scripts/run_root_test_bins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ fi

for ((repeat = 0; repeat < REPEATS; repeat++)); do
for prefix in \
"liblzma-" \
"xz-" \
"drop_incomplete-" \
"sys_equivalence-" \
"xz-"
"standard_files-"
do
BIN=""
while IFS= read -r candidate; do
Expand All @@ -40,7 +40,7 @@ for ((repeat = 0; repeat < REPEATS; repeat++)); do
exit 1
fi
ARGS=(--test-threads=1)
if [[ "$prefix" == "liblzma-" ]]; then
if [[ "$prefix" == "xz-" ]]; then
# QuickCheck-based tests use a fresh RNG per process, so backend-to-backend
# wall-clock comparisons on them are not stable. Cover those paths with
# deterministic focused probes instead.
Expand Down
16 changes: 8 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//! LZMA/XZ encoding and decoding streams
//!
//! This library is a binding to liblzma currently to provide LZMA and xz
//! encoding/decoding streams. I/O streams are provided in the `read`, `write`,
//! This library provides LZMA and xz encoding/decoding streams.
//! I/O streams are provided in the `read`, `write`,
//! and `bufread` modules (same types, different bounds). Raw in-memory
//! compression/decompression is provided via the `stream` module and contains
//! many of the raw APIs in liblzma.
//! many of the raw APIs exposed by the selected backend.
//!
//! # Examples
//!
//! ```no_run
//! use liblzma::read::{XzDecoder, XzEncoder};
//! use xz::read::{XzDecoder, XzEncoder};
//! use std::io::prelude::*;
//!
//! // Round trip some bytes from a byte source, into a compressor, into a
Expand All @@ -25,10 +25,10 @@
//! # Static linking
//!
//! You can enable static-linking using the `static` feature, so that the XZ
//! library is not required at runtime:
//! library is not required at runtime when using the `liblzma-sys` backend:
//!
//! ```toml
//! liblzma = { version = "0.4", features = ["static"] }
//! xz = { version = "0.4", default-features = false, features = ["liblzma-sys", "static"] }
//! ```
//!
//! # Multithreading
Expand All @@ -37,7 +37,7 @@
//! feature of this crate:
//!
//! ```toml
//! liblzma = { version = "0.4", features = ["parallel"] }
//! xz = { version = "0.4", features = ["parallel"] }
//! ```
//!
//! # Async I/O
Expand All @@ -49,7 +49,7 @@
//! async-compression = { version = "0.4", features = ["lzma"] }
//! ```

#![doc(html_root_url = "https://docs.rs/liblzma/0.4.6")]
#![doc(html_root_url = "https://docs.rs/xz/0.4.6")]
#![deny(missing_docs)]

#[cfg(any(
Expand Down
Loading