diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ffd7fc38..176c792d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: matrix: include: - os: ubuntu-latest - rust: '1.60' # msrv + rust: '1.63' # msrv - os: ubuntu-latest rust: stable - os: ubuntu-latest @@ -56,11 +56,11 @@ jobs: run: echo LZMA_API_STATIC=1 >> $GITHUB_ENV shell: bash - name: copy Cargo.lock for msrv check - if: matrix.rust == '1.60' + if: matrix.rust == '1.63' run: | cp Cargo.lock.msrv Cargo.lock - run: | - cargo test --no-default-features + cargo test --no-default-features --features rust-backend cargo clean -p liblzma -p liblzma-sys - run: | cargo test --features parallel diff --git a/.github/workflows/webassembly.yml b/.github/workflows/webassembly.yml index 247c5b92..a902a299 100644 --- a/.github/workflows/webassembly.yml +++ b/.github/workflows/webassembly.yml @@ -45,17 +45,17 @@ jobs: name: Run test run: | cargo test --locked --target ${{ matrix.target }} --features wasm - - if: ${{ endsWith(matrix.target, 'unknown') }} + - if: ${{ matrix.target == 'wasm32-unknown-unknown' }} name: Run test run: | curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash - cargo binstall -y --force wasm-bindgen-cli + cargo binstall -y --force wasm-bindgen-cli@0.2.115 cargo test --locked --target ${{ matrix.target }} --features wasm --release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For ease GitHub API rate limits - name: Run test if: ${{ startsWith(matrix.target, 'wasm32-unknown-emscripten') }} run: | - cargo test --locked --target ${{ matrix.target }} --features wasm -- --skip standard_files + cargo test --locked --target ${{ matrix.target }} --lib --tests --features wasm -- --skip standard_files env: RUSTFLAGS: "-C link-args=-sINITIAL_MEMORY=128MB" diff --git a/Cargo.lock.msrv b/Cargo.lock.msrv index 7e0a1cef..4561c938 100644 --- a/Cargo.lock.msrv +++ b/Cargo.lock.msrv @@ -4,13 +4,42 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + [[package]] name = "bitflags" version = "1.3.2" @@ -18,25 +47,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bitflags" -version = "2.9.0" +name = "bumpalo" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] -name = "bumpalo" -version = "3.17.0" +name = "cast" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.49" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ + "find-msvc-tools", "jobserver", - "num_cpus", + "libc", + "shlex", ] [[package]] @@ -47,20 +78,129 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "console_error_panic_hook" -version = "0.1.7" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen", + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "ctest2" version = "0.4.10" @@ -93,6 +233,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "env_logger" version = "0.8.4" @@ -103,6 +249,36 @@ dependencies = [ "regex", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + [[package]] name = "garando_errors" version = "0.1.0" @@ -131,7 +307,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d8a383861d12fc78c251bbcb1ec252dd8338714ce02ab0cc393cfd02f40d32b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "garando_errors", "garando_pos", "log", @@ -142,79 +318,132 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 1.0.4", + "js-sys", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.2.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ - "cfg-if 1.0.0", - "js-sys", + "cfg-if 1.0.4", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", - "wasm-bindgen", + "r-efi", + "wasip2", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if 1.0.4", + "crunchy", + "zerocopy", ] [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jobserver" -version = "0.1.16" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.4", "libc", - "log", - "rand 0.7.3", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "cc4c90f45aa2e6eacbe8645f77fdea542ac97a494bcd117a67df9ff4d611f995" dependencies = [ + "cfg-if 1.0.4", + "futures-util", "once_cell", "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.150" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "liblzma" version = "0.4.6" dependencies = [ - "getrandom 0.2.5", + "criterion", + "getrandom 0.2.17", + "liblzma-rs-sys", "liblzma-sys", + "log", "num_cpus", "quickcheck", - "rand 0.8.5", + "rand", + "regex", "wasm-bindgen-test", ] +[[package]] +name = "liblzma-rs" +version = "0.1.0" +dependencies = [ + "libc", + "memchr", +] + +[[package]] +name = "liblzma-rs-sys" +version = "0.1.0" +dependencies = [ + "libc", + "liblzma-rs", +] + [[package]] name = "liblzma-sys" version = "0.4.5" @@ -224,33 +453,67 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ - "bitflags 2.9.0", "libc", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "minicov" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d" +dependencies = [ + "cc", + "walkdir", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -258,120 +521,158 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.18" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quickcheck" -version = "1.0.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +checksum = "efc008b226fa5bdeabfc788d6679692223e940da371a95e26d87678333dac7c8" dependencies = [ "env_logger", "log", - "rand 0.8.5", + "rand", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.7.3" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "a76330fb486679b4ace3670f117bbc9e16204005c4bde9c4bd372f45bed34f12" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", + "rand_chacha", + "rand_core", + "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.5.1", + "rand_core", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "getrandom 0.2.17", ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "rand_hc" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "7b363d4f6370f88d62bf586c80405657bde0f0e1b8945d47d2ad59b906cb4f54" dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "rayon" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ - "getrandom 0.2.5", + "either", + "rayon-core", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "rayon-core" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ - "rand_core 0.5.1", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -380,7 +681,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.5", + "getrandom 0.2.17", "libredox", "thiserror", ] @@ -425,42 +726,49 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] -name = "ryu" -version = "1.0.20" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] -name = "scoped-tls" -version = "1.0.1" +name = "semver" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] -name = "semver" -version = "1.0.26" +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] [[package]] -name = "serde" -version = "1.0.219" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -469,21 +777,34 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + [[package]] name = "syn" -version = "2.0.100" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -496,6 +817,7 @@ version = "0.1.0" dependencies = [ "ctest2", "libc", + "liblzma-rs-sys", "liblzma-sys", ] @@ -529,11 +851,21 @@ dependencies = [ "syn", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-xid" @@ -542,61 +874,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasm-bindgen" +version = "0.2.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "6523d69017b7633e396a89c5efab138161ed5aafcbc8d3e5c5a42ae38f50495a" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", + "cfg-if 1.0.4", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "2d1faf851e778dfa54db7cd438b70758eba9755cb47403f3496edd7c8fc212f0" dependencies = [ - "cfg-if 1.0.0", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "4e3a6c758eb2f701ed3d052ff5737f5bfe6614326ea7f3bbac7156192dc32e67" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -604,56 +933,70 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "921de2737904886b52bcbb237301552d05969a6f9c40d261eb0533c8b055fedf" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "a93e946af942b58934c604527337bad9ae33ba1d5c6900bbb41c2c07c2364a93" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.42" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b" +checksum = "1138411301a026d6662dc44e7076a74dbaa76a369312275eea5dee4d7dc68c7c" dependencies = [ - "console_error_panic_hook", + "async-trait", + "cast", "js-sys", - "scoped-tls", + "libm", + "minicov", + "nu-ansi-term", + "num-traits", + "oorandom", + "serde", + "serde_json", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", + "wasm-bindgen-test-shared", ] [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.42" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" +checksum = "186ddfe8383ba7ae7927bae3bb7343fd1f03ba2dbaf1474410f0d831131c269b" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "wasm-bindgen-test-shared" +version = "0.2.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f032e076ceb8d36d5921c6cef5bf447f2ca2bbd5439ce1683d68d1c99cc2be16" + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "84cde8507f4d7cfcb1185b8cb5890c494ffea65edbe1ba82cfd63661c805ed94" dependencies = [ "js-sys", "wasm-bindgen", @@ -675,8 +1018,64 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "zerocopy" +version = "0.8.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index a62c4917..088c1a99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,38 +13,53 @@ in-memory encoding/decoding. forked from xz2. """ categories = ["compression", "api-bindings"] edition = "2021" -rust-version = "1.60" +rust-version = "1.63" exclude = [".github/"] [workspace] -members = ["systest"] +members = ["systest", "liblzma-rs", "liblzma-rs-sys"] [dependencies] -liblzma-sys = { path = "liblzma-sys", version = "0.4.3", default-features = false } +# Rust backend (default) - pure Rust implementation +liblzma-sys = { package = "liblzma-rs-sys", path = "liblzma-rs-sys", optional = true } +# C backend - original liblzma C library via FFI +liblzma-c-sys = { package = "liblzma-sys", path = "liblzma-sys", version = "0.4.5", optional = true, default-features = false } num_cpus = { version = "1.16.0", optional = true } +criterion = { version = "0.5", features = ["html_reports"], optional = true } [dev-dependencies] -rand = "0.8.0" -quickcheck = "1.0.1" +rand = "=0.8.0" +regex = "=1.9.0" +log = "=0.4.20" + +[[bench]] +name = "backend_comparison" +harness = false +required-features = ["bench"] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] getrandom = { version = "0.2", features = ["js"] } +[target.'cfg(not(target_family = "wasm"))'.dev-dependencies] +quickcheck = "=1.0.1" + [target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dev-dependencies] wasm-bindgen-test = "0.3" [features] -default = ["bindgen"] -static = ["liblzma-sys/static"] -parallel = ["liblzma-sys/parallel", "num_cpus"] -bindgen = ["liblzma-sys/bindgen"] -wasm = ["liblzma-sys/wasm"] -uncheck_liblzma_version = ["liblzma-sys/uncheck_liblzma_version"] # Disables version checking for the system-installed liblzma. This is not recommended under normal circumstances. - -# These two are for cross-language LTO. -# Will only work if `clang` is used to build the C library. -fat-lto = ["liblzma-sys/fat-lto"] # Enable fat-lto, will override thin-lto if specified -thin-lto = ["liblzma-sys/thin-lto"] # Enable thin-lto, will fall back to fat-lto if not supported +default = ["rust-backend"] +rust-backend = ["liblzma-sys"] +c-backend = ["liblzma-c-sys/bindgen"] +static = ["liblzma-c-sys?/static"] +parallel = ["liblzma-sys?/parallel", "liblzma-c-sys?/parallel", "num_cpus"] +bindgen = ["liblzma-c-sys?/bindgen"] # ignored for rust-backend +wasm = ["liblzma-sys?/wasm", "liblzma-c-sys?/wasm"] +uncheck_liblzma_version = ["liblzma-c-sys?/uncheck_liblzma_version"] # ignored for rust-backend +bench = ["criterion"] +# These two are for cross-language LTO with the C backend. +# Ignored for rust-backend. +fat-lto = ["liblzma-c-sys?/fat-lto"] +thin-lto = ["liblzma-c-sys?/thin-lto"] [package.metadata.docs.rs] features = ["parallel"] diff --git a/benches/backend_comparison.rs b/benches/backend_comparison.rs new file mode 100644 index 00000000..ee3c4130 --- /dev/null +++ b/benches/backend_comparison.rs @@ -0,0 +1,181 @@ +#![cfg(not(target_family = "wasm"))] + +use std::ptr; + +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +use liblzma_c_sys as c_sys; +use liblzma_sys as rs_sys; + +fn make_payload(size: usize) -> Vec { + let mut x: u64 = 0x9E3779B97F4A7C15; + let mut out = Vec::with_capacity(size); + for _ in 0..size { + x ^= x >> 12; + x ^= x << 25; + x ^= x >> 27; + out.push((x.wrapping_mul(0x2545F4914F6CDD1D) >> 56) as u8); + } + out +} + +unsafe fn c_encode(input: &[u8]) -> Vec { + let bound = c_sys::lzma_stream_buffer_bound(input.len()); + let mut out = vec![0u8; bound]; + let mut out_pos: usize = 0; + c_sys::lzma_easy_buffer_encode( + 6, + c_sys::LZMA_CHECK_CRC64, + ptr::null(), + input.as_ptr(), + input.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + out.truncate(out_pos); + out +} + +unsafe fn rs_encode(input: &[u8]) -> Vec { + let bound = rs_sys::lzma_stream_buffer_bound(input.len()); + let mut out = vec![0u8; bound]; + let mut out_pos: usize = 0; + rs_sys::lzma_easy_buffer_encode( + 6, + rs_sys::LZMA_CHECK_CRC64, + ptr::null(), + input.as_ptr(), + input.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + out.truncate(out_pos); + out +} + +unsafe fn c_decode(compressed: &[u8], out_size: usize) -> Vec { + let mut out = vec![0u8; out_size]; + let mut memlimit = u64::MAX; + let mut in_pos = 0usize; + let mut out_pos = 0usize; + c_sys::lzma_stream_buffer_decode( + &mut memlimit, + 0, + ptr::null(), + compressed.as_ptr(), + &mut in_pos, + compressed.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + out.truncate(out_pos); + out +} + +unsafe fn rs_decode(compressed: &[u8], out_size: usize) -> Vec { + let mut out = vec![0u8; out_size]; + let mut memlimit = u64::MAX; + let mut in_pos = 0usize; + let mut out_pos = 0usize; + rs_sys::lzma_stream_buffer_decode( + &mut memlimit, + 0, + ptr::null(), + compressed.as_ptr(), + &mut in_pos, + compressed.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + out.truncate(out_pos); + out +} + +fn bench_encode(c: &mut Criterion) { + let sizes: &[(usize, &str)] = &[(1024, "1KB"), (64 * 1024, "64KB"), (1024 * 1024, "1MB")]; + + let mut group = c.benchmark_group("encode"); + for &(size, label) in sizes { + let input = make_payload(size); + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_with_input(BenchmarkId::new("c", label), &input, |b, input| { + b.iter(|| unsafe { c_encode(black_box(input)) }) + }); + group.bench_with_input(BenchmarkId::new("rust", label), &input, |b, input| { + b.iter(|| unsafe { rs_encode(black_box(input)) }) + }); + } + group.finish(); +} + +fn bench_decode(c: &mut Criterion) { + let sizes: &[(usize, &str)] = &[(1024, "1KB"), (64 * 1024, "64KB"), (1024 * 1024, "1MB")]; + + let mut group = c.benchmark_group("decode"); + for &(size, label) in sizes { + let input = make_payload(size); + let c_compressed = unsafe { c_encode(&input) }; + let rs_compressed = unsafe { rs_encode(&input) }; + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_with_input(BenchmarkId::new("c", label), &c_compressed, |b, data| { + b.iter(|| unsafe { c_decode(black_box(data), size) }) + }); + group.bench_with_input( + BenchmarkId::new("rust", label), + &rs_compressed, + |b, data| b.iter(|| unsafe { rs_decode(black_box(data), size) }), + ); + } + group.finish(); +} + +fn bench_crc32(c: &mut Criterion) { + let sizes: &[(usize, &str)] = &[(1024, "1KB"), (64 * 1024, "64KB"), (1024 * 1024, "1MB")]; + + let mut group = c.benchmark_group("crc32"); + for &(size, label) in sizes { + let data = make_payload(size); + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_with_input(BenchmarkId::new("c", label), &data, |b, data| { + b.iter(|| unsafe { c_sys::lzma_crc32(black_box(data.as_ptr()), data.len(), 0) }) + }); + group.bench_with_input(BenchmarkId::new("rust", label), &data, |b, data| { + b.iter(|| unsafe { rs_sys::lzma_crc32(black_box(data.as_ptr()), data.len(), 0) }) + }); + } + group.finish(); +} + +fn bench_crc64(c: &mut Criterion) { + let sizes: &[(usize, &str)] = &[(1024, "1KB"), (64 * 1024, "64KB"), (1024 * 1024, "1MB")]; + + let mut group = c.benchmark_group("crc64"); + for &(size, label) in sizes { + let data = make_payload(size); + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_with_input(BenchmarkId::new("c", label), &data, |b, data| { + b.iter(|| unsafe { c_sys::lzma_crc64(black_box(data.as_ptr()), data.len(), 0) }) + }); + group.bench_with_input(BenchmarkId::new("rust", label), &data, |b, data| { + b.iter(|| unsafe { rs_sys::lzma_crc64(black_box(data.as_ptr()), data.len(), 0) }) + }); + } + group.finish(); +} + +criterion_group!( + benches, + bench_encode, + bench_decode, + bench_crc32, + bench_crc64 +); +criterion_main!(benches); diff --git a/liblzma-rs-sys/Cargo.toml b/liblzma-rs-sys/Cargo.toml new file mode 100644 index 00000000..c9b7be0c --- /dev/null +++ b/liblzma-rs-sys/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "liblzma-rs-sys" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "liblzma-sys compatible API layer backed by pure Rust liblzma-rs" + +[lib] +crate-type = ["rlib", "staticlib"] + +[features] +default = ["bindgen"] +# The following features exist for compatibility with liblzma-sys. +# Since this crate is a pure Rust implementation, they are ignored. +static = [] # ignored: no C library to link statically +bindgen = [] # ignored: no C headers to generate bindings from +fat-lto = [] # ignored: no C object files for cross-language LTO +thin-lto = [] # ignored: no C object files for cross-language LTO +uncheck_liblzma_version = [] # ignored: no system liblzma to version-check +# These features have actual effects: +parallel = [] +wasm = ["static", "bindgen"] + +[dependencies] +liblzma-rs = { path = "../liblzma-rs" } +libc = "0.2" diff --git a/liblzma-rs-sys/src/lib.rs b/liblzma-rs-sys/src/lib.rs new file mode 100644 index 00000000..dc0e191a --- /dev/null +++ b/liblzma-rs-sys/src/lib.rs @@ -0,0 +1,1142 @@ +//! liblzma-sys compatible API layer backed by pure Rust liblzma-rs +//! +//! Re-exports symbols from liblzma-rs with the same names and signatures +//! as liblzma-sys, enabling drop-in replacement. +//! +//! Because c2rust generates per-file type definitions, this layer provides +//! canonical types and thin wrapper functions that cast between structurally +//! identical `#[repr(C)]` types. + +#![allow( + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_imports, + clippy::all +)] + +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +use libc::size_t; +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +use libc::{c_char, c_int, c_uchar, c_uint, c_void}; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +use std::os::raw::{c_char, c_int, c_uchar, c_uint, c_void}; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +type wasm_size_t = usize; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +use self::wasm_size_t as size_t; + +// === Canonical type aliases === +// On MSVC, C enums are c_int; elsewhere c_uint (matching liblzma-sys manual.rs) +#[cfg(target_env = "msvc")] +#[doc(hidden)] +pub type __enum_ty = c_int; +#[cfg(not(target_env = "msvc"))] +#[doc(hidden)] +pub type __enum_ty = c_uint; + +pub type lzma_ret = __enum_ty; +pub type lzma_action = __enum_ty; +pub type lzma_check = __enum_ty; +pub type lzma_mode = __enum_ty; +pub type lzma_match_finder = __enum_ty; +pub type lzma_bool = c_uchar; +pub type lzma_vli = u64; + +// === Canonical struct re-exports === +pub use liblzma_rs::common::index_hash::lzma_index_hash; +pub use liblzma_rs::types::lzma_allocator; +pub use liblzma_rs::types::lzma_block; +pub use liblzma_rs::types::lzma_filter; +pub use liblzma_rs::types::lzma_index; +pub use liblzma_rs::types::lzma_index_iter; +pub use liblzma_rs::types::lzma_index_iter_mode; +pub use liblzma_rs::types::lzma_mt; +pub use liblzma_rs::types::lzma_options_lzma; +pub use liblzma_rs::types::lzma_stream; +pub use liblzma_rs::types::lzma_stream_flags; + +#[repr(C)] +pub struct lzma_options_bcj { + pub start_offset: u32, +} + +pub enum lzma_internal {} + +// ========================================================================= +// Constants +// ========================================================================= + +// --- Return codes --- +pub use liblzma_rs::types::{ + LZMA_BUF_ERROR, LZMA_DATA_ERROR, LZMA_FORMAT_ERROR, LZMA_GET_CHECK, LZMA_MEMLIMIT_ERROR, + LZMA_MEM_ERROR, LZMA_NO_CHECK, LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_PROG_ERROR, LZMA_SEEK_NEEDED, + LZMA_STREAM_END, LZMA_UNSUPPORTED_CHECK, +}; + +// --- Actions --- +pub use liblzma_rs::types::{ + LZMA_FINISH, LZMA_FULL_BARRIER, LZMA_FULL_FLUSH, LZMA_RUN, LZMA_SYNC_FLUSH, +}; + +// --- Check types --- +pub use liblzma_rs::types::{ + LZMA_CHECK_CRC32, LZMA_CHECK_CRC64, LZMA_CHECK_NONE, LZMA_CHECK_SHA256, +}; + +// --- Modes / match finders --- +pub use liblzma_rs::types::{ + LZMA_MF_BT2, LZMA_MF_BT3, LZMA_MF_BT4, LZMA_MF_HC3, LZMA_MF_HC4, LZMA_MODE_FAST, + LZMA_MODE_NORMAL, +}; + +// --- Filter IDs --- +pub use liblzma_rs::types::{ + LZMA_FILTER_ARM, LZMA_FILTER_ARM64, LZMA_FILTER_ARMTHUMB, LZMA_FILTER_DELTA, LZMA_FILTER_IA64, + LZMA_FILTER_LZMA1, LZMA_FILTER_LZMA2, LZMA_FILTER_POWERPC, LZMA_FILTER_RISCV, + LZMA_FILTER_SPARC, LZMA_FILTER_X86, +}; + +// --- Decoder flags --- +pub use liblzma_rs::types::{ + LZMA_CONCATENATED, LZMA_IGNORE_CHECK, LZMA_TELL_ANY_CHECK, LZMA_TELL_NO_CHECK, + LZMA_TELL_UNSUPPORTED_CHECK, +}; + +// --- Presets / option limits --- +pub const LZMA_PRESET_DEFAULT: u32 = + liblzma_rs::common::string_conversion::LZMA_PRESET_DEFAULT as u32; +pub const LZMA_PRESET_LEVEL_MASK: u32 = + liblzma_rs::lzma::lzma_encoder_presets::LZMA_PRESET_LEVEL_MASK as u32; +pub const LZMA_PRESET_EXTREME: u32 = liblzma_rs::types::LZMA_PRESET_EXTREME as u32; +pub const LZMA_DICT_SIZE_MIN: u32 = liblzma_rs::types::LZMA_DICT_SIZE_MIN as u32; +pub const LZMA_DICT_SIZE_DEFAULT: u32 = + liblzma_rs::common::string_conversion::LZMA_DICT_SIZE_DEFAULT as u32; +pub const LZMA_LCLP_MIN: u32 = liblzma_rs::common::string_conversion::LZMA_LCLP_MIN as u32; +pub const LZMA_LCLP_MAX: u32 = liblzma_rs::types::LZMA_LCLP_MAX as u32; +pub const LZMA_LC_DEFAULT: u32 = liblzma_rs::lzma::lzma_encoder_presets::LZMA_LC_DEFAULT as u32; +pub const LZMA_LP_DEFAULT: u32 = liblzma_rs::lzma::lzma_encoder_presets::LZMA_LP_DEFAULT as u32; +pub const LZMA_PB_MIN: u32 = liblzma_rs::common::string_conversion::LZMA_PB_MIN as u32; +pub const LZMA_PB_MAX: u32 = liblzma_rs::types::LZMA_PB_MAX as u32; +pub const LZMA_PB_DEFAULT: u32 = liblzma_rs::lzma::lzma_encoder_presets::LZMA_PB_DEFAULT as u32; + +// --- Backward size / VLI --- +pub const LZMA_BACKWARD_SIZE_MIN: lzma_vli = liblzma_rs::types::LZMA_BACKWARD_SIZE_MIN as lzma_vli; +pub const LZMA_BACKWARD_SIZE_MAX: lzma_vli = liblzma_rs::types::LZMA_BACKWARD_SIZE_MAX as lzma_vli; +pub use liblzma_rs::types::{LZMA_VLI_MAX, LZMA_VLI_UNKNOWN}; +pub const LZMA_VLI_BYTES_MAX: usize = liblzma_rs::types::LZMA_VLI_BYTES_MAX as usize; + +// --- Stream header size --- +pub const LZMA_STREAM_HEADER_SIZE: u32 = liblzma_rs::types::LZMA_STREAM_HEADER_SIZE as u32; + +// ========================================================================= +// Functions +// ========================================================================= +// +// Functions are exposed as thin C ABI wrappers from this crate. +// Wrappers cast to canonical Rust implementation types and forward the call. + +// --- Common stream API --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_code(strm: *mut lzma_stream, action: lzma_action) -> lzma_ret { + liblzma_rs::common::common::lzma_code(strm.cast(), action) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_end(strm: *mut lzma_stream) { + liblzma_rs::common::common::lzma_end(strm.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_memlimit_get(strm: *const lzma_stream) -> u64 { + liblzma_rs::common::common::lzma_memlimit_get(strm.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_memlimit_set(strm: *mut lzma_stream, new_memlimit: u64) -> lzma_ret { + liblzma_rs::common::common::lzma_memlimit_set(strm.cast(), new_memlimit) +} + +// --- Version --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_version_number() -> u32 { + liblzma_rs::common::common::lzma_version_number() +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_version_string() -> *const c_char { + liblzma_rs::common::common::lzma_version_string() +} + +// --- Progress / memusage --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_get_progress( + strm: *mut lzma_stream, + progress_in: *mut u64, + progress_out: *mut u64, +) { + liblzma_rs::common::common::lzma_get_progress(strm.cast(), progress_in, progress_out) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_memusage(strm: *const lzma_stream) -> u64 { + liblzma_rs::common::common::lzma_memusage(strm.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_get_check(strm: *const lzma_stream) -> lzma_check { + liblzma_rs::common::common::lzma_get_check(strm.cast()) +} + +// --- Check --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_check_is_supported(check: lzma_check) -> lzma_bool { + liblzma_rs::check::check::lzma_check_is_supported(check) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_check_size(check: lzma_check) -> u32 { + liblzma_rs::check::check::lzma_check_size(check) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_crc32(buf: *const u8, size: size_t, crc: u32) -> u32 { + liblzma_rs::check::crc32_fast::lzma_crc32(buf, size, crc) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_crc64(buf: *const u8, size: size_t, crc: u64) -> u64 { + liblzma_rs::check::crc64_fast::lzma_crc64(buf, size, crc) +} + +// --- Easy encoder --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_easy_encoder_memusage(preset: u32) -> u64 { + liblzma_rs::common::easy_encoder_memusage::lzma_easy_encoder_memusage(preset) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_easy_decoder_memusage(preset: u32) -> u64 { + liblzma_rs::common::easy_decoder_memusage::lzma_easy_decoder_memusage(preset) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_easy_encoder( + strm: *mut lzma_stream, + preset: u32, + check: lzma_check, +) -> lzma_ret { + liblzma_rs::common::easy_encoder::lzma_easy_encoder(strm.cast(), preset, check) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_easy_buffer_encode( + preset: u32, + check: lzma_check, + allocator: *const lzma_allocator, + input: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::easy_buffer_encoder::lzma_easy_buffer_encode( + preset, + check, + allocator.cast(), + input, + in_size, + out, + out_pos, + out_size, + ) +} + +// --- Stream encoder/decoder --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_encoder( + strm: *mut lzma_stream, + filters: *const lzma_filter, + check: lzma_check, +) -> lzma_ret { + liblzma_rs::common::stream_encoder::lzma_stream_encoder(strm.cast(), filters.cast(), check) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_decoder( + strm: *mut lzma_stream, + memlimit: u64, + flags: u32, +) -> lzma_ret { + liblzma_rs::common::stream_decoder::lzma_stream_decoder(strm.cast(), memlimit, flags) +} + +// --- Alone encoder/decoder --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_alone_encoder( + strm: *mut lzma_stream, + options: *const lzma_options_lzma, +) -> lzma_ret { + liblzma_rs::common::alone_encoder::lzma_alone_encoder(strm.cast(), options.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_alone_decoder(strm: *mut lzma_stream, memlimit: u64) -> lzma_ret { + liblzma_rs::common::alone_decoder::lzma_alone_decoder(strm.cast(), memlimit) +} + +// --- Auto/lzip decoder --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_auto_decoder( + strm: *mut lzma_stream, + memlimit: u64, + flags: u32, +) -> lzma_ret { + liblzma_rs::common::auto_decoder::lzma_auto_decoder(strm.cast(), memlimit, flags) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_lzip_decoder( + strm: *mut lzma_stream, + memlimit: u64, + flags: u32, +) -> lzma_ret { + liblzma_rs::common::lzip_decoder::lzma_lzip_decoder(strm.cast(), memlimit, flags) +} + +// --- Stream buffer --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_buffer_bound(uncompressed_size: size_t) -> size_t { + liblzma_rs::common::stream_buffer_encoder::lzma_stream_buffer_bound(uncompressed_size) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_buffer_encode( + filters: *mut lzma_filter, + check: lzma_check, + allocator: *const lzma_allocator, + input: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::stream_buffer_encoder::lzma_stream_buffer_encode( + filters.cast(), + check, + allocator.cast(), + input, + in_size, + out, + out_pos, + out_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_buffer_decode( + memlimit: *mut u64, + flags: u32, + allocator: *const lzma_allocator, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::stream_buffer_decoder::lzma_stream_buffer_decode( + memlimit, + flags, + allocator.cast(), + input, + in_pos, + in_size, + out, + out_pos, + out_size, + ) +} + +// --- Filter --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_filter_encoder_is_supported(id: lzma_vli) -> lzma_bool { + liblzma_rs::common::filter_encoder::lzma_filter_encoder_is_supported(id) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_filter_decoder_is_supported(id: lzma_vli) -> lzma_bool { + liblzma_rs::common::filter_decoder::lzma_filter_decoder_is_supported(id) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_filters_copy( + src: *const lzma_filter, + dest: *mut lzma_filter, + allocator: *const lzma_allocator, +) -> lzma_ret { + liblzma_rs::common::filter_common::lzma_filters_copy(src.cast(), dest.cast(), allocator.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_raw_encoder_memusage(filters: *const lzma_filter) -> u64 { + liblzma_rs::common::filter_encoder::lzma_raw_encoder_memusage(filters.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_raw_decoder_memusage(filters: *const lzma_filter) -> u64 { + liblzma_rs::common::filter_decoder::lzma_raw_decoder_memusage(filters.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_raw_encoder( + strm: *mut lzma_stream, + filters: *const lzma_filter, +) -> lzma_ret { + liblzma_rs::common::filter_encoder::lzma_raw_encoder(strm.cast(), filters.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_raw_decoder( + strm: *mut lzma_stream, + filters: *const lzma_filter, +) -> lzma_ret { + liblzma_rs::common::filter_decoder::lzma_raw_decoder(strm.cast(), filters.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_filters_update( + strm: *mut lzma_stream, + filters: *const lzma_filter, +) -> lzma_ret { + liblzma_rs::common::filter_encoder::lzma_filters_update(strm.cast(), filters.cast()) +} + +// --- Raw buffer --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_raw_buffer_encode( + filters: *const lzma_filter, + allocator: *const lzma_allocator, + input: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::filter_buffer_encoder::lzma_raw_buffer_encode( + filters.cast(), + allocator.cast(), + input, + in_size, + out, + out_pos, + out_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_raw_buffer_decode( + filters: *const lzma_filter, + allocator: *const lzma_allocator, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::filter_buffer_decoder::lzma_raw_buffer_decode( + filters.cast(), + allocator.cast(), + input, + in_pos, + in_size, + out, + out_pos, + out_size, + ) +} + +// --- Properties --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_properties_size( + size: *mut u32, + filter: *const lzma_filter, +) -> lzma_ret { + liblzma_rs::common::filter_encoder::lzma_properties_size(size, filter.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_properties_encode( + filter: *const lzma_filter, + props: *mut u8, +) -> lzma_ret { + liblzma_rs::common::filter_encoder::lzma_properties_encode(filter.cast(), props) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_properties_decode( + filter: *mut lzma_filter, + allocator: *const lzma_allocator, + props: *const u8, + props_size: size_t, +) -> lzma_ret { + liblzma_rs::common::filter_decoder::lzma_properties_decode( + filter.cast(), + allocator.cast(), + props, + props_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_mt_block_size(filters: *const lzma_filter) -> u64 { + liblzma_rs::common::filter_encoder::lzma_mt_block_size(filters.cast()) +} + +// --- LZMA preset --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_lzma_preset( + options: *mut lzma_options_lzma, + preset: u32, +) -> lzma_bool { + liblzma_rs::lzma::lzma_encoder_presets::lzma_lzma_preset(options.cast(), preset) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_mf_is_supported(mf: lzma_match_finder) -> lzma_bool { + liblzma_rs::lz::lz_encoder::lzma_mf_is_supported(mf) +} + +// --- Stream header/footer --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_header_encode( + options: *const lzma_stream_flags, + out: *mut u8, +) -> lzma_ret { + liblzma_rs::common::stream_flags_encoder::lzma_stream_header_encode(options.cast(), out) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_footer_encode( + options: *const lzma_stream_flags, + out: *mut u8, +) -> lzma_ret { + liblzma_rs::common::stream_flags_encoder::lzma_stream_footer_encode(options.cast(), out) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_header_decode( + options: *mut lzma_stream_flags, + input: *const u8, +) -> lzma_ret { + liblzma_rs::common::stream_flags_decoder::lzma_stream_header_decode(options.cast(), input) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_footer_decode( + options: *mut lzma_stream_flags, + input: *const u8, +) -> lzma_ret { + liblzma_rs::common::stream_flags_decoder::lzma_stream_footer_decode(options.cast(), input) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_flags_compare( + a: *const lzma_stream_flags, + b: *const lzma_stream_flags, +) -> lzma_ret { + liblzma_rs::common::stream_flags_common::lzma_stream_flags_compare(a.cast(), b.cast()) +} + +// --- VLI --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_vli_encode( + vli: lzma_vli, + vli_pos: *mut size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::vli_encoder::lzma_vli_encode(vli, vli_pos, out, out_pos, out_size) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_vli_decode( + vli: *mut lzma_vli, + vli_pos: *mut size_t, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + liblzma_rs::common::vli_decoder::lzma_vli_decode(vli, vli_pos, input, in_pos, in_size) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_vli_size(vli: lzma_vli) -> u32 { + liblzma_rs::common::vli_size::lzma_vli_size(vli) +} + +// --- Hardware --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_physmem() -> u64 { + liblzma_rs::common::hardware_physmem::lzma_physmem() +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_cputhreads() -> u32 { + liblzma_rs::common::hardware_cputhreads::lzma_cputhreads() +} + +// --- Index --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_buffer_decode( + i: *mut *mut lzma_index, + memlimit: *mut u64, + allocator: *const lzma_allocator, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + liblzma_rs::common::index_decoder::lzma_index_buffer_decode( + i.cast(), + memlimit, + allocator.cast(), + input, + in_pos, + in_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_uncompressed_size(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_uncompressed_size(i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_end(i: *mut lzma_index, allocator: *const lzma_allocator) { + liblzma_rs::common::index::lzma_index_end(i.cast(), allocator.cast()) +} + +// --- Block --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_header_size(block: *mut lzma_block) -> lzma_ret { + liblzma_rs::common::block_header_encoder::lzma_block_header_size(block.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_header_encode( + block: *const lzma_block, + out: *mut u8, +) -> lzma_ret { + liblzma_rs::common::block_header_encoder::lzma_block_header_encode(block.cast(), out) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_header_decode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + input: *const u8, +) -> lzma_ret { + liblzma_rs::common::block_header_decoder::lzma_block_header_decode( + block.cast(), + allocator.cast(), + input, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_compressed_size( + block: *mut lzma_block, + unpadded_size: lzma_vli, +) -> lzma_ret { + liblzma_rs::common::block_util::lzma_block_compressed_size(block.cast(), unpadded_size) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_unpadded_size(block: *const lzma_block) -> lzma_vli { + liblzma_rs::common::block_util::lzma_block_unpadded_size(block.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_total_size(block: *const lzma_block) -> lzma_vli { + liblzma_rs::common::block_util::lzma_block_total_size(block.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_encoder( + strm: *mut lzma_stream, + block: *mut lzma_block, +) -> lzma_ret { + liblzma_rs::common::block_encoder::lzma_block_encoder(strm.cast(), block.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_decoder( + strm: *mut lzma_stream, + block: *mut lzma_block, +) -> lzma_ret { + liblzma_rs::common::block_decoder::lzma_block_decoder(strm.cast(), block.cast()) +} + +#[no_mangle] +pub extern "C" fn lzma_block_buffer_bound(uncompressed_size: size_t) -> size_t { + liblzma_rs::common::block_buffer_encoder::lzma_block_buffer_bound(uncompressed_size) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_buffer_encode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + input: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::block_buffer_encoder::lzma_block_buffer_encode( + block.cast(), + allocator.cast(), + input, + in_size, + out, + out_pos, + out_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_uncomp_encode( + block: *mut lzma_block, + input: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::block_buffer_encoder::lzma_block_uncomp_encode( + block.cast(), + input, + in_size, + out, + out_pos, + out_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_block_buffer_decode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::block_buffer_decoder::lzma_block_buffer_decode( + block.cast(), + allocator.cast(), + input, + in_pos, + in_size, + out, + out_pos, + out_size, + ) +} + +// --- Index (extended) --- + +#[no_mangle] +pub extern "C" fn lzma_index_memusage(streams: lzma_vli, blocks: lzma_vli) -> u64 { + liblzma_rs::common::index::lzma_index_memusage(streams, blocks) +} + +#[no_mangle] +pub extern "C" fn lzma_index_memused(i: *const lzma_index) -> u64 { + liblzma_rs::common::index::lzma_index_memused(i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_init(allocator: *const lzma_allocator) -> *mut lzma_index { + liblzma_rs::common::index::lzma_index_init(allocator.cast()).cast() +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_append( + i: *mut lzma_index, + allocator: *const lzma_allocator, + unpadded_size: lzma_vli, + uncompressed_size: lzma_vli, +) -> lzma_ret { + liblzma_rs::common::index::lzma_index_append( + i.cast(), + allocator.cast(), + unpadded_size, + uncompressed_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_stream_flags( + i: *mut lzma_index, + stream_flags: *const lzma_stream_flags, +) -> lzma_ret { + liblzma_rs::common::index::lzma_index_stream_flags(i.cast(), stream_flags.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_checks(i: *const lzma_index) -> u32 { + liblzma_rs::common::index::lzma_index_checks(i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_stream_padding( + i: *mut lzma_index, + stream_padding: lzma_vli, +) -> lzma_ret { + liblzma_rs::common::index::lzma_index_stream_padding(i.cast(), stream_padding) +} + +#[no_mangle] +pub extern "C" fn lzma_index_stream_count(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_stream_count(i.cast()) +} + +#[no_mangle] +pub extern "C" fn lzma_index_block_count(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_block_count(i.cast()) +} + +#[no_mangle] +pub extern "C" fn lzma_index_size(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_size(i.cast()) +} + +#[no_mangle] +pub extern "C" fn lzma_index_stream_size(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_stream_size(i.cast()) +} + +#[no_mangle] +pub extern "C" fn lzma_index_total_size(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_total_size(i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_file_size(i: *const lzma_index) -> lzma_vli { + liblzma_rs::common::index::lzma_index_file_size(i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_iter_init(iter: *mut lzma_index_iter, i: *const lzma_index) { + liblzma_rs::common::index::lzma_index_iter_init(iter.cast(), i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_iter_rewind(iter: *mut lzma_index_iter) { + liblzma_rs::common::index::lzma_index_iter_rewind(iter.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_iter_next( + iter: *mut lzma_index_iter, + mode: lzma_index_iter_mode, +) -> lzma_bool { + liblzma_rs::common::index::lzma_index_iter_next(iter.cast(), mode) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_iter_locate( + iter: *mut lzma_index_iter, + target: lzma_vli, +) -> lzma_bool { + liblzma_rs::common::index::lzma_index_iter_locate(iter.cast(), target) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_cat( + dest: *mut lzma_index, + src: *mut lzma_index, + allocator: *const lzma_allocator, +) -> lzma_ret { + liblzma_rs::common::index::lzma_index_cat(dest.cast(), src.cast(), allocator.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_dup( + i: *const lzma_index, + allocator: *const lzma_allocator, +) -> *mut lzma_index { + liblzma_rs::common::index::lzma_index_dup(i.cast(), allocator.cast()).cast() +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_encoder( + strm: *mut lzma_stream, + i: *const lzma_index, +) -> lzma_ret { + liblzma_rs::common::index_encoder::lzma_index_encoder(strm.cast(), i.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_decoder( + strm: *mut lzma_stream, + i: *mut *mut lzma_index, + memlimit: u64, +) -> lzma_ret { + liblzma_rs::common::index_decoder::lzma_index_decoder(strm.cast(), i.cast(), memlimit) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_buffer_encode( + i: *const lzma_index, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::index_encoder::lzma_index_buffer_encode(i.cast(), out, out_pos, out_size) +} + +// --- Index hash --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_hash_init( + index_hash: *mut lzma_index_hash, + allocator: *const lzma_allocator, +) -> *mut lzma_index_hash { + liblzma_rs::common::index_hash::lzma_index_hash_init(index_hash.cast(), allocator.cast()).cast() +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_hash_end( + index_hash: *mut lzma_index_hash, + allocator: *const lzma_allocator, +) { + liblzma_rs::common::index_hash::lzma_index_hash_end(index_hash.cast(), allocator.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_hash_append( + index_hash: *mut lzma_index_hash, + unpadded_size: lzma_vli, + uncompressed_size: lzma_vli, +) -> lzma_ret { + liblzma_rs::common::index_hash::lzma_index_hash_append( + index_hash.cast(), + unpadded_size, + uncompressed_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_index_hash_decode( + index_hash: *mut lzma_index_hash, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + liblzma_rs::common::index_hash::lzma_index_hash_decode( + index_hash.cast(), + input, + in_pos, + in_size, + ) +} + +#[no_mangle] +pub extern "C" fn lzma_index_hash_size(index_hash: *const lzma_index_hash) -> lzma_vli { + liblzma_rs::common::index_hash::lzma_index_hash_size(index_hash.cast()) +} + +// --- Filter flags/string --- + +#[no_mangle] +pub unsafe extern "C" fn lzma_filter_flags_size( + size: *mut u32, + filter: *const lzma_filter, +) -> lzma_ret { + liblzma_rs::common::filter_flags_encoder::lzma_filter_flags_size(size, filter.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_filter_flags_encode( + filter: *const lzma_filter, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + liblzma_rs::common::filter_flags_encoder::lzma_filter_flags_encode( + filter.cast(), + out, + out_pos, + out_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_filter_flags_decode( + filter: *mut lzma_filter, + allocator: *const lzma_allocator, + input: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + liblzma_rs::common::filter_flags_decoder::lzma_filter_flags_decode( + filter.cast(), + allocator.cast(), + input, + in_pos, + in_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_filters_free( + filters: *mut lzma_filter, + allocator: *const lzma_allocator, +) { + liblzma_rs::common::filter_common::lzma_filters_free(filters.cast(), allocator.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_str_to_filters( + str_: *const c_char, + error_pos: *mut c_int, + filters: *mut lzma_filter, + flags: u32, + allocator: *const lzma_allocator, +) -> *const c_char { + liblzma_rs::common::string_conversion::lzma_str_to_filters( + str_, + error_pos, + filters.cast(), + flags, + allocator.cast(), + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_str_from_filters( + str_: *mut *mut c_char, + filters: *const lzma_filter, + flags: u32, + allocator: *const lzma_allocator, +) -> lzma_ret { + liblzma_rs::common::string_conversion::lzma_str_from_filters( + str_, + filters.cast(), + flags, + allocator.cast(), + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_str_list_filters( + str_: *mut *mut c_char, + filter_id: lzma_vli, + flags: u32, + allocator: *const lzma_allocator, +) -> lzma_ret { + liblzma_rs::common::string_conversion::lzma_str_list_filters( + str_, + filter_id, + flags, + allocator.cast(), + ) +} + +// --- Misc --- + +#[no_mangle] +pub extern "C" fn lzma_mode_is_supported(mode: lzma_mode) -> lzma_bool { + liblzma_rs::lzma::lzma_encoder::lzma_mode_is_supported(mode) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_microlzma_encoder( + strm: *mut lzma_stream, + options: *const lzma_options_lzma, +) -> lzma_ret { + liblzma_rs::common::microlzma_encoder::lzma_microlzma_encoder(strm.cast(), options.cast()) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_microlzma_decoder( + strm: *mut lzma_stream, + comp_size: u64, + uncomp_size: u64, + uncomp_size_is_exact: lzma_bool, + dict_size: u32, +) -> lzma_ret { + liblzma_rs::common::microlzma_decoder::lzma_microlzma_decoder( + strm.cast(), + comp_size, + uncomp_size, + uncomp_size_is_exact, + dict_size, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn lzma_file_info_decoder( + strm: *mut lzma_stream, + i: *mut *mut lzma_index, + memlimit: u64, + file_size: u64, +) -> lzma_ret { + liblzma_rs::common::file_info::lzma_file_info_decoder( + strm.cast(), + i.cast(), + memlimit, + file_size, + ) +} + +// ========================================================================= +// Multithreaded API +// ========================================================================= + +#[cfg(feature = "parallel")] +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_encoder_mt( + strm: *mut lzma_stream, + options: *const lzma_mt, +) -> lzma_ret { + liblzma_rs::common::stream_mt::lzma_stream_encoder_mt(strm.cast(), options.cast()) +} + +#[cfg(feature = "parallel")] +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_decoder_mt( + strm: *mut lzma_stream, + options: *const lzma_mt, +) -> lzma_ret { + liblzma_rs::common::stream_mt::lzma_stream_decoder_mt(strm.cast(), options.cast()) +} + +#[cfg(feature = "parallel")] +#[no_mangle] +pub unsafe extern "C" fn lzma_stream_encoder_mt_memusage(options: *const lzma_mt) -> u64 { + liblzma_rs::common::stream_mt::lzma_stream_encoder_mt_memusage(options.cast()) +} diff --git a/liblzma-rs/Cargo.toml b/liblzma-rs/Cargo.toml new file mode 100644 index 00000000..b8c718ac --- /dev/null +++ b/liblzma-rs/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "liblzma-rs" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +description = "Pure Rust implementation of liblzma (transpiled from C via c2rust)" + +[features] +default = [] + +[dependencies] +libc = "0.2" +memchr = "2" diff --git a/liblzma-rs/src/alloc.rs b/liblzma-rs/src/alloc.rs new file mode 100644 index 00000000..00f8a9ff --- /dev/null +++ b/liblzma-rs/src/alloc.rs @@ -0,0 +1,196 @@ +use crate::types::*; +use std::alloc::{alloc, alloc_zeroed, dealloc, Layout}; + +const RUST_ALLOC_ALIGN: usize = 16; + +#[derive(Copy, Clone)] +#[repr(C)] +struct RustAllocHeader { + total_size: usize, + align: usize, + offset: usize, +} + +const fn round_up(value: usize, align: usize) -> usize { + (value + (align - 1)) & !(align - 1) +} + +unsafe fn rust_alloc_impl(size: usize, align: usize, zeroed: bool) -> *mut c_void { + let size = if size == 0 { 1 } else { size }; + let align = align + .max(RUST_ALLOC_ALIGN) + .max(core::mem::align_of::()); + let header_size = core::mem::size_of::(); + let offset = match header_size.checked_add(align - 1) { + Some(value) => round_up(value, align), + None => return core::ptr::null_mut(), + }; + let total_size = match offset.checked_add(size) { + Some(total_size) => total_size, + None => return core::ptr::null_mut(), + }; + let layout = match Layout::from_size_align(total_size, align) { + Ok(layout) => layout, + Err(_) => return core::ptr::null_mut(), + }; + let base = if zeroed { + alloc_zeroed(layout) + } else { + alloc(layout) + }; + if base.is_null() { + return core::ptr::null_mut(); + } + let user_ptr = base.add(offset); + let header_ptr = user_ptr.sub(header_size) as *mut RustAllocHeader; + header_ptr.write(RustAllocHeader { + total_size, + align, + offset, + }); + user_ptr as *mut c_void +} + +unsafe fn rust_free_impl(ptr: *mut c_void) { + if ptr.is_null() { + return; + } + let header_size = core::mem::size_of::(); + let user_ptr = ptr as *mut u8; + let header_ptr = user_ptr.sub(header_size) as *const RustAllocHeader; + let header = header_ptr.read(); + let base = user_ptr.sub(header.offset); + let layout = Layout::from_size_align_unchecked(header.total_size, header.align); + dealloc(base, layout); +} + +pub unsafe extern "C" fn lzma_rust_alloc( + _opaque: *mut c_void, + nmemb: size_t, + size: size_t, +) -> *mut c_void { + let size = match (nmemb as usize).checked_mul(size as usize) { + Some(size) => size, + None => return core::ptr::null_mut(), + }; + rust_alloc_impl(size, RUST_ALLOC_ALIGN, false) +} + +pub unsafe extern "C" fn lzma_rust_free(_opaque: *mut c_void, ptr: *mut c_void) { + rust_free_impl(ptr); +} + +pub fn rust_allocator() -> lzma_allocator { + lzma_allocator { + alloc: Some(lzma_rust_alloc), + free: Some(lzma_rust_free), + opaque: core::ptr::null_mut(), + } +} + +pub(crate) unsafe fn internal_alloc_bytes( + size: size_t, + allocator: *const lzma_allocator, +) -> *mut c_void { + let size = if size == 0 { 1 } else { size }; + if !allocator.is_null() && (*allocator).alloc.is_some() { + (*allocator).alloc.unwrap()((*allocator).opaque, 1, size) + } else { + rust_alloc_impl(size as usize, RUST_ALLOC_ALIGN, false) + } +} + +pub(crate) unsafe fn internal_alloc_zeroed_bytes( + size: size_t, + allocator: *const lzma_allocator, +) -> *mut c_void { + let size = if size == 0 { 1 } else { size }; + if !allocator.is_null() && (*allocator).alloc.is_some() { + let ptr = (*allocator).alloc.unwrap()((*allocator).opaque, 1, size); + if !ptr.is_null() { + core::ptr::write_bytes(ptr as *mut u8, 0, size); + } + ptr + } else { + rust_alloc_impl(size as usize, RUST_ALLOC_ALIGN, true) + } +} + +pub(crate) unsafe fn internal_alloc_object(allocator: *const lzma_allocator) -> *mut T { + if !allocator.is_null() && (*allocator).alloc.is_some() { + return (*allocator).alloc.unwrap()( + (*allocator).opaque, + 1, + core::mem::size_of::() as size_t, + ) as *mut T; + } + rust_alloc_impl(core::mem::size_of::(), core::mem::align_of::(), false) as *mut T +} + +pub(crate) unsafe fn internal_alloc_array( + count: size_t, + allocator: *const lzma_allocator, +) -> *mut T { + let size = match (count as usize).checked_mul(core::mem::size_of::()) { + Some(size) => size, + None => return core::ptr::null_mut(), + }; + if !allocator.is_null() && (*allocator).alloc.is_some() { + return (*allocator).alloc.unwrap()((*allocator).opaque, 1, size as size_t) as *mut T; + } + rust_alloc_impl(size, core::mem::align_of::(), false) as *mut T +} + +pub(crate) unsafe fn internal_alloc_zeroed_array( + count: size_t, + allocator: *const lzma_allocator, +) -> *mut T { + let size = match (count as usize).checked_mul(core::mem::size_of::()) { + Some(size) => size, + None => return core::ptr::null_mut(), + }; + if !allocator.is_null() && (*allocator).alloc.is_some() { + let ptr = (*allocator).alloc.unwrap()((*allocator).opaque, 1, size as size_t) as *mut T; + if !ptr.is_null() { + core::ptr::write_bytes(ptr as *mut u8, 0, size); + } + return ptr; + } + rust_alloc_impl(size, core::mem::align_of::(), true) as *mut T +} + +pub(crate) unsafe fn internal_free(ptr: *mut c_void, allocator: *const lzma_allocator) { + if !allocator.is_null() && (*allocator).free.is_some() { + (*allocator).free.unwrap()((*allocator).opaque, ptr); + } else { + rust_free_impl(ptr); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rust_allocator_round_trip() { + unsafe { + let allocator = rust_allocator(); + let ptr = allocator.alloc.unwrap()(allocator.opaque, 4, 8); + assert!(!ptr.is_null()); + allocator.free.unwrap()(allocator.opaque, ptr); + } + } + + #[test] + fn internal_object_allocation_respects_alignment() { + #[repr(align(32))] + struct Align32([u8; 32]); + + unsafe { + let ptr = internal_alloc_object::(core::ptr::null()); + assert!(!ptr.is_null()); + assert_eq!((ptr as usize) % core::mem::align_of::(), 0); + internal_free(ptr.cast(), core::ptr::null()); + } + } +} diff --git a/liblzma-rs/src/check/check.rs b/liblzma-rs/src/check/check.rs new file mode 100644 index 00000000..7197ebb4 --- /dev/null +++ b/liblzma-rs/src/check/check.rs @@ -0,0 +1,96 @@ +use crate::check::crc64_fast::lzma_crc64; +use crate::check::sha256::{lzma_sha256_finish, lzma_sha256_init, lzma_sha256_update}; +use crate::types::*; +pub fn lzma_check_is_supported(type_0: lzma_check) -> lzma_bool { + if type_0 > LZMA_CHECK_ID_MAX { + return false as lzma_bool; + } + static available_checks: [lzma_bool; 16] = [ + true as lzma_bool, + true as lzma_bool, + false as lzma_bool, + false as lzma_bool, + true as lzma_bool, + false as lzma_bool, + false as lzma_bool, + false as lzma_bool, + false as lzma_bool, + false as lzma_bool, + true as lzma_bool, + false as lzma_bool, + false as lzma_bool, + false as lzma_bool, + false as lzma_bool, + false as lzma_bool, + ]; + available_checks[type_0 as usize] +} +pub fn lzma_check_size(type_0: lzma_check) -> u32 { + if type_0 > LZMA_CHECK_ID_MAX { + return UINT32_MAX; + } + static check_sizes: [u8; 16] = [ + 0, 4 as u8, 4 as u8, 4 as u8, 8 as u8, 8 as u8, 8 as u8, 16 as u8, 16 as u8, 16 as u8, + 32 as u8, 32 as u8, 32 as u8, 64 as u8, 64 as u8, 64 as u8, + ]; + check_sizes[type_0 as usize] as u32 +} +pub unsafe fn lzma_check_init(check: *mut lzma_check_state, type_0: lzma_check) { + if check.is_null() { + return; + } + + match type_0 { + LZMA_CHECK_CRC32 => { + (*check).state.crc32 = 0; + } + LZMA_CHECK_CRC64 => { + (*check).state.crc64 = 0; + } + LZMA_CHECK_SHA256 => { + lzma_sha256_init(check); + } + LZMA_CHECK_NONE | _ => {} + }; +} +pub unsafe fn lzma_check_update( + check: *mut lzma_check_state, + type_0: lzma_check, + buf: *const u8, + size: size_t, +) { + if check.is_null() { + return; + } + + match type_0 { + LZMA_CHECK_CRC32 => { + (*check).state.crc32 = lzma_crc32(buf, size, (*check).state.crc32); + } + LZMA_CHECK_CRC64 => { + (*check).state.crc64 = lzma_crc64(buf, size, (*check).state.crc64); + } + LZMA_CHECK_SHA256 => { + lzma_sha256_update(buf, size, check); + } + _ => {} + }; +} +pub unsafe fn lzma_check_finish(check: *mut lzma_check_state, type_0: lzma_check) { + if check.is_null() { + return; + } + + match type_0 { + LZMA_CHECK_CRC32 => { + (*check).buffer.u32_0[0] = (*check).state.crc32; + } + LZMA_CHECK_CRC64 => { + (*check).buffer.u64_0[0] = (*check).state.crc64; + } + LZMA_CHECK_SHA256 => { + lzma_sha256_finish(check); + } + _ => {} + }; +} diff --git a/liblzma-rs/src/check/crc32_fast.rs b/liblzma-rs/src/check/crc32_fast.rs new file mode 100644 index 00000000..b27f1e92 --- /dev/null +++ b/liblzma-rs/src/check/crc32_fast.rs @@ -0,0 +1,355 @@ +use crate::types::*; +pub static lzma_crc32_table: [[u32; 256]; 8] = [ + [ + 0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, + 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, + 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, + 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, + 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, + 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, + 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, + 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, + 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, + 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, + 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, + 0x9309ff9d, 0xa00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, + 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, + 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, + 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, + 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, + 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, + 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, + 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + ], + [ + 0, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, + 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, 0x2eaed755, 0x37b5e614, + 0x1c98b5d7, 0x5838496, 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, + 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, + 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, + 0x7670fd69, 0x39316bae, 0x202a5aef, 0xb07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, 0x179fbcfb, + 0xe848dba, 0x25a9de79, 0x3cb2ef38, 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, + 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, 0xa623e883, + 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0xa96a78f, 0x138d96ce, 0x5ccc0009, 0x45d73148, + 0x6efa628b, 0x77e153ca, 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, + 0x160e1258, 0xf152319, 0x243870da, 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, + 0x4ed03864, 0x191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, 0xb43fd0ee, + 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, 0x2f3f79f6, + 0x362448b7, 0x1d091b74, 0x4122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, 0x9a9107bb, 0xb1bc5478, + 0xa8a76539, 0x3b83984b, 0x2298a90a, 0x9b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, + 0x6dd93fcd, 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, 0x9736d747, + 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, + 0x152d4f1e, 0xc367e5f, 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, 0xae07bce9, 0xb71c8da8, + 0x9c31de6b, 0x852aef2a, 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, + 0x7fc507a0, 0x54e85463, 0x4df36522, 0x2b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, + 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, 0x80a96bbc, 0x99b25afd, 0xb29f093e, + 0xab84387f, 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x7317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, 0xaf96124a, + 0xb68d230b, 0x9da070c8, 0x84bb4189, 0x3235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, + 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, 0xb30ea79d, + 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, 0x49e14f17, 0x50fa7e56, + 0x7bd72d95, 0x62cc1cd4, 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x6a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, 0x824546a, 0x113f652b, + 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, + 0xd9e6ef23, 0x14bce1bd, 0xda7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, 0x69cb15f8, + 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, 0xb809aeb1, + 0xa1129ff0, 0x8a3fcc33, 0x9324fd72, + ], + [ + 0, 0x1c26a37, 0x384d46e, 0x246be59, 0x709a8dc, 0x6cbc2eb, 0x48d7cb2, 0x54f1685, 0xe1351b8, + 0xfd13b8f, 0xd9785d6, 0xc55efe1, 0x91af964, 0x8d89353, 0xa9e2d0a, 0xb5c473d, 0x1c26a370, + 0x1de4c947, 0x1fa2771e, 0x1e601d29, 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, + 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, 0x16b88e7a, + 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, + 0x3cc03a52, 0x3d025065, 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, + 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, + 0x283e0a71, 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, 0x7158e7f7, + 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, 0x7e89dc78, + 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, 0x6a77ec5b, 0x68315202, + 0x69f33835, 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, + 0x662203ba, 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, 0x4fde63fc, + 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, + 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, 0x5ae239e8, 0x5b2053df, + 0x5966ed86, 0x58a487b1, 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, + 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, + 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, + 0xea695cbd, 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, 0xf4094194, + 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, + 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, + 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, 0xc55efe10, 0xc49c9427, + 0xc6da2a7e, 0xc7184049, 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, + 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, + 0x94e080c5, 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, 0x99770513, + 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, + 0x8b42f7db, 0x89044982, 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, + 0xaba46ef9, 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, + 0xa4755576, 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, 0xb5c473d0, + 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, + 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed, + ], + [ + 0, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, + 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, 0xdf7bc0c8, 0x67c7a7ad, + 0x75720843, 0xcdce6f26, 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, + 0xa2738f42, 0xb0c620ac, 0x87a47c9, 0xa032af3e, 0x188ec85b, 0xa3b67b5, 0xb28700d0, + 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, + 0x7733283f, 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, 0x359fd04e, + 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, 0xbafd4719, 0x241207c, 0x10f48f92, 0xa848e8f7, + 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, + 0x6c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, 0xd1c2e785, 0x697e80e0, + 0x7bcb2f0e, 0xc377486b, 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0xeb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, + 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, + 0x299358ed, 0xb4446054, 0xcf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, 0x462eb889, + 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, 0x6b3fa09c, + 0xd383c7f9, 0xc1366817, 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x48240f8, 0xbc3e279d, 0x21e91f24, 0x99557841, 0x8be0d7af, + 0x335cb0ca, 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, + 0xc832e9e7, 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, 0xa78f0983, + 0x1f336ee6, 0xd86c108, 0xb53aa66d, 0xbd40e1a4, 0x5fc86c1, 0x1749292f, 0xaff54e4a, + 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, 0x4d6b1905, 0xf5d77e60, + 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, + 0x3063568f, 0x22d6f961, 0x9a6a9e04, 0x7bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, + 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0xfc7e174, 0x9210d9cd, 0x2aacbea8, 0x38191146, + 0x80a57623, 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, 0xf92f7951, + 0x41931e34, 0x5326b1da, 0xeb9ad6bf, 0xb3f9c6e9, 0xb45a18c, 0x19f00e62, 0xa14c6907, + 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, 0x8c5d7112, + 0x34e11677, 0xa9362ece, 0x118a49ab, 0x33fe645, 0xbb838120, 0xe3e09176, 0x5b5cf613, + 0x49e959fd, 0xf1553e98, 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, + 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x17ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, + 0x8e1c516e, 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x90481f0, 0xb1b8e695, + 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, + 0x740cce7a, 0x66b96194, 0xde0506f1, + ], + [ + 0, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, + 0x30704bc1, 0xd106271, 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, 0x95603142, 0xa80018f2, + 0xefa06222, 0xd2c04b92, 0x5090dc43, 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, + 0x98705333, 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, 0x866155d4, + 0x344189c4, 0x921a074, 0x4e81daa4, 0x73e1f314, 0xf1b164c5, 0xccd14d75, 0x8b7137a5, + 0xb6111e15, 0x431c205, 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, 0x13016496, 0x9151f347, + 0xac31daf7, 0xeb91a027, 0xd6f18997, 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, + 0x58f35849, 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, 0xd7b3ade9, + 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, 0x2f236958, 0x9d03b548, 0xa0639cf8, + 0xe7c3e628, 0xdaa3cf98, 0x3813cfcb, 0x573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x863840a, 0x3503adba, 0x72a3d76a, 0x4fc3feda, + 0xfde322ca, 0xc0830b7a, 0x872371aa, 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, + 0xde920d9d, 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, 0x9422153c, + 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, + 0xc4b2c97f, 0x8312b3af, 0xbe729a1f, 0xc52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, 0x142247e, 0x46e25eae, + 0x7b82771e, 0xb1e6b092, 0x8c869922, 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, + 0x3ea64532, 0x3c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, 0x74165d93, + 0x49767423, 0xed60ef3, 0x33b62743, 0xd1062710, 0xec660ea0, 0xabc67470, 0x96a65dc0, + 0x248681d0, 0x19e6a860, 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, 0x70279f96, 0x4d47b626, + 0xae7ccf6, 0x3787e546, 0x85a73956, 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, + 0x7d37fde7, 0x3a978737, 0x7f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, 0xf2770847, + 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, 0xe547aed4, 0xd8278764, 0x9f87fdb4, + 0xa2e7d404, 0x20b743d5, 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, 0xaeb5920b, 0x1c954e1b, + 0x21f567ab, 0x66551d7b, 0x5b3534cb, 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, + 0x2ce505da, 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, 0xf3352c39, + 0xce550589, 0x7c75d999, 0x4115f029, 0x6b58af9, 0x3bd5a349, 0xb9853498, 0x84e51d28, + 0xc34567f8, 0xfe254e48, 0x4c059258, 0x7165bbe8, 0x36c5c138, 0xba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, 0xa794327f, 0x9af41bcf, + 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, + 0xaa84500e, 0x4834505d, 0x755479ed, 0x32f4033d, 0xf942a8d, 0xbdb4f69d, 0x80d4df2d, + 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, 0x28448fc, 0x3fe4614c, 0x8dc4bd5c, + 0xb0a494ec, 0xf704ee3c, 0xca64c78c, + ], + [ + 0, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, 0x50cd91b3, 0xd659e31d, 0x1d0530b8, + 0xec53826d, 0x270f51c8, 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x3d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, 0x9847408d, 0x531b9328, + 0xd58fe186, 0x1ed33223, 0xef8580f6, 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, + 0xbf481145, 0x39dc63eb, 0xf280b04e, 0x7ac0536, 0xccf0d693, 0x4a64a43d, 0x81387798, + 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, 0xebff875b, 0x20a354fe, 0xa6372650, + 0x6d6bf5f5, 0x706ec54d, 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x47a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, 0x197f3715, 0xe82985c0, + 0x23755665, 0xa5e124cb, 0x6ebdf76e, 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, + 0xf580a6c, 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, 0xd901e971, + 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, 0x659ffaaf, 0x789aca17, 0xb3c619b2, + 0x35526b1c, 0xfe0eb8b9, 0xc8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, 0xad152b91, 0x6649f834, + 0x7b4cc88c, 0xb0101b29, 0x36846987, 0xfdd8ba22, 0x8f40f5a, 0xc3a8dcff, 0x453cae51, + 0x8e607df4, 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, 0x2ffb5e92, + 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, 0x32fe6e2a, 0xf9a2bd8f, 0xb220dc1, + 0xc07ede64, 0x46eaacca, 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, 0xb7bc1e1f, 0x31286cb1, + 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, + 0xc8e9f7c5, 0x3b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, 0x6972d4a3, + 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, + 0x86f75455, 0x4dab87f0, 0xcb3ff55e, 0x6326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, 0x191c11ee, 0xd240c24b, + 0x54d4b0e5, 0x9f886340, 0x828d53f8, 0x49d1805d, 0xcf45f2f3, 0x4192156, 0xf54f9383, + 0x3e134026, 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, 0xe84aa33b, + 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, 0x815b5163, 0x4a0782c6, 0xcc93f068, + 0x7cf23cd, 0xf6999118, 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, 0x977c6c1a, 0x8a795ca2, + 0x41258f07, 0xc7b1fda9, 0xced2e0c, 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, + 0x662adecf, 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, 0x5ff6bd24, + 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, 0xf3b2c97, 0xfe6d9e42, 0x35314de7, + 0xb3a53f49, 0x78f9ecec, 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, 0xc01df89f, 0xb412b3a, + 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, + 0xe712a957, 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, 0x455f88aa, + 0xc3cbfa04, 0x89729a1, 0xf9c19b74, 0x329d48d1, 0xb4093a7f, 0x7f55e9da, 0x6250d962, + 0xa90c0ac7, 0x2f987869, 0xe4c4abcc, + ], + [ + 0, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, 0x52382fa7, 0x63d0353a, 0xc5a73e8e, + 0x33ef4e67, 0x959845d3, 0xa4705f4e, 0x20754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, 0x9391b8dd, 0x35e6b369, + 0x40ea9f4, 0xa279a240, 0x5431d2a9, 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, + 0x609fd0e, 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, 0xfe552301, + 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0xa1a0712, 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, + 0xcdba6d66, 0x81d53e8, 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0xe14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, 0x6dc49bdc, 0x9b8ceb35, + 0x3dfbe081, 0xc13fa1c, 0xaa64f1a8, 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, + 0x440b7579, 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, 0x27db4043, + 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, 0x460c2183, 0x83ab1f0d, 0x25dc14b9, + 0x14340e24, 0xb2430590, 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, 0x87a5b6f9, 0x21d2bd4d, + 0xe47583c3, 0x42028877, 0x73ea92ea, 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, + 0xba5e5678, 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, 0x1e2e0936, + 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, + 0x4a1fdb9f, 0x7bf7c102, 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, 0x8dbfb1eb, 0xbc57ab76, + 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, + 0xebc6dfc8, 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, 0x4fb68086, + 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, 0x49bf7d88, 0x78576715, 0xde206ca1, + 0x1b87522f, 0xbdf0599b, 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, 0x47abd36e, 0xe1dcd8da, + 0xd034c247, 0x7643c9f3, 0xb3e4f77d, 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, + 0xd23396bd, 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, 0xb1e3a387, + 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, 0xd43a6bb3, 0x724d6007, 0x43a57a9a, + 0xe5d2712e, 0x139a01c7, 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, 0xfdf58516, 0x3852bb98, + 0x9e25b02c, 0xafcdaab1, 0x9baa105, 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, + 0xbbdf5ff, 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0xdb408f1, 0x3c5c126c, + 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, 0x6e643dcb, 0x982c4d22, 0x3e5b4696, + 0xfb35c0b, 0xa9c457bf, 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x3a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, 0x6070932d, 0xc6079899, + 0x304fe870, 0x9638e3c4, 0xa7d0f959, 0x1a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, + 0xf5e8d6fe, 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, 0x3646157e, + 0x7ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, 0xc00e6597, 0x66796e23, 0xa3de50ad, + 0x5a95b19, 0x34414184, 0x92364a30, + ], + [ + 0, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, 0x48e00e64, 0xc66f0987, 0xac50919, + 0xd3e51bb5, 0x1f4f1b2b, 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, 0xf8f13fd1, 0x345b3f4f, + 0xbad438ac, 0x767e3832, 0xaf5e2a9e, 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, + 0xe7be24fa, 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, 0x77f965b5, + 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, 0x2a9379e3, 0xe639797d, 0x68b67e9e, + 0xa41c7e00, 0xaed97719, 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0xb42549e, 0x1875d87, 0xcd2d5d19, 0x43a25afa, 0x8f085a64, 0x562848c8, + 0x9a824856, 0x140d4fb5, 0xd8a74f2b, 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, + 0x299dc2ed, 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, 0xeff2cb6a, + 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, 0x74f7debb, 0x7e32d7a2, 0xb298d73c, + 0x3c17d0df, 0xf0bdd041, 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, 0xc4e6ef0e, 0x84cef90, + 0x289e689, 0xce23e617, 0x40ace1f4, 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, + 0x5e64a758, 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x30ebb0e, 0xcfa4bb90, + 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, 0xc561b289, 0x9cbb217, 0xac509190, + 0x60fa910e, 0xee7596ed, 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, 0x37558441, 0xb9da83a2, + 0x7570833c, 0x533b85da, 0x9f918544, 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, + 0x95548c5d, 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0xe51998c, 0x4949095, + 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, 0xe32ab46f, 0x6da5b38c, 0xa10fb312, + 0xabcaba0b, 0x6760ba95, 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, 0xaa4de78c, 0x66e7e712, + 0xe868e0f1, 0x24c2e06f, 0x2e07e976, 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, + 0xb502fca7, 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, 0x736df520, + 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, 0x52bcd85d, 0x9e16d8c3, 0x1099df20, + 0xdc33dfbe, 0x513cd12, 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0xfd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, 0xf42940d4, 0xfeec49cd, + 0x32464953, 0xbcc94eb0, 0x70634e2e, 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, + 0x2d095278, 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x61d761c, 0xcab77682, 0x44387161, + 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, 0xcd87f05, 0xd5f86da9, 0x19526d37, + 0x97dd6ad4, 0x5b776a4a, 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0xd5f2282, 0x79a2b9b, 0xcb302b05, 0x45bf2ce6, 0x89152c78, + 0x50353ed4, 0x9c9f3e4a, 0x121039a9, 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, + 0x5af037cd, 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, + 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, + 0x646e019b, 0xeae10678, 0x264b06e6, + ], +]; +unsafe fn lzma_crc32_generic(mut buf: *const u8, mut size: size_t, mut crc: u32) -> u32 { + crc = !crc; + if size > 8 { + while buf as uintptr_t & 7 as uintptr_t != 0 { + crc = lzma_crc32_table[0][(*buf as u32 ^ crc & 0xff) as usize] ^ crc >> 8; + buf = buf.offset(1); + size -= 1; + } + let limit: *const u8 = buf.offset((size & !(7)) as isize); + size &= 7; + while buf < limit { + crc ^= aligned_read32ne(buf); + buf = buf.offset(4); + crc = lzma_crc32_table[7][(crc & 0xff) as usize] + ^ lzma_crc32_table[6][(crc >> 8 & 0xff) as usize] + ^ lzma_crc32_table[5][(crc >> 16 & 0xff) as usize] + ^ lzma_crc32_table[4][(crc >> 24) as usize]; + let tmp: u32 = aligned_read32ne(buf) as u32; + buf = buf.offset(4); + crc = lzma_crc32_table[3][(tmp & 0xff) as usize] + ^ lzma_crc32_table[2][(tmp >> 8 & 0xff) as usize] + ^ crc + ^ lzma_crc32_table[1][(tmp >> 16 & 0xff) as usize] + ^ lzma_crc32_table[0][(tmp >> 24) as usize]; + } + } + loop { + let old_size = size; + size = size.wrapping_sub(1); + if old_size == 0 { + break; + } + crc = lzma_crc32_table[0][(*buf as u32 ^ crc & 0xff) as usize] ^ crc >> 8; + buf = buf.offset(1); + } + !crc +} +pub unsafe fn lzma_crc32(buf: *const u8, size: size_t, crc: u32) -> u32 { + lzma_crc32_generic(buf, size, crc) +} diff --git a/liblzma-rs/src/check/crc64_fast.rs b/liblzma-rs/src/check/crc64_fast.rs new file mode 100644 index 00000000..16bef208 --- /dev/null +++ b/liblzma-rs/src/check/crc64_fast.rs @@ -0,0 +1,1066 @@ +use crate::types::*; +pub static mut lzma_crc64_table: [[u64; 256]; 4] = [ + [ + 0, + 0xb32e4cbe03a75f6f, + 0xf4843657a840a05b, + 0x47aa7ae9abe7ff34, + 0x7bd0c384ff8f5e33, + 0xc8fe8f3afc28015c, + 0x8f54f5d357cffe68, + 0x3c7ab96d5468a107, + 0xf7a18709ff1ebc66, + 0x448fcbb7fcb9e309, + 0x325b15e575e1c3d, + 0xb00bfde054f94352, + 0x8c71448d0091e255, + 0x3f5f08330336bd3a, + 0x78f572daa8d1420e, + 0xcbdb3e64ab761d61, + 0x7d9ba13851336649, + 0xceb5ed8652943926, + 0x891f976ff973c612, + 0x3a31dbd1fad4997d, + 0x64b62bcaebc387a, + 0xb5652e02ad1b6715, + 0xf2cf54eb06fc9821, + 0x41e11855055bc74e, + 0x8a3a2631ae2dda2f, + 0x39146a8fad8a8540, + 0x7ebe1066066d7a74, + 0xcd905cd805ca251b, + 0xf1eae5b551a2841c, + 0x42c4a90b5205db73, + 0x56ed3e2f9e22447, + 0xb6409f5cfa457b28, + 0xfb374270a266cc92, + 0x48190ecea1c193fd, + 0xfb374270a266cc9, + 0xbc9d3899098133a6, + 0x80e781f45de992a1, + 0x33c9cd4a5e4ecdce, + 0x7463b7a3f5a932fa, + 0xc74dfb1df60e6d95, + 0xc96c5795d7870f4, + 0xbfb889c75edf2f9b, + 0xf812f32ef538d0af, + 0x4b3cbf90f69f8fc0, + 0x774606fda2f72ec7, + 0xc4684a43a15071a8, + 0x83c230aa0ab78e9c, + 0x30ec7c140910d1f3, + 0x86ace348f355aadb, + 0x3582aff6f0f2f5b4, + 0x7228d51f5b150a80, + 0xc10699a158b255ef, + 0xfd7c20cc0cdaf4e8, + 0x4e526c720f7dab87, + 0x9f8169ba49a54b3, + 0xbad65a25a73d0bdc, + 0x710d64410c4b16bd, + 0xc22328ff0fec49d2, + 0x85895216a40bb6e6, + 0x36a71ea8a7ace989, + 0xadda7c5f3c4488e, + 0xb9f3eb7bf06317e1, + 0xfe5991925b84e8d5, + 0x4d77dd2c5823b7ba, + 0x64b62bcaebc387a1, + 0xd7986774e864d8ce, + 0x90321d9d438327fa, + 0x231c512340247895, + 0x1f66e84e144cd992, + 0xac48a4f017eb86fd, + 0xebe2de19bc0c79c9, + 0x58cc92a7bfab26a6, + 0x9317acc314dd3bc7, + 0x2039e07d177a64a8, + 0x67939a94bc9d9b9c, + 0xd4bdd62abf3ac4f3, + 0xe8c76f47eb5265f4, + 0x5be923f9e8f53a9b, + 0x1c4359104312c5af, + 0xaf6d15ae40b59ac0, + 0x192d8af2baf0e1e8, + 0xaa03c64cb957be87, + 0xeda9bca512b041b3, + 0x5e87f01b11171edc, + 0x62fd4976457fbfdb, + 0xd1d305c846d8e0b4, + 0x96797f21ed3f1f80, + 0x2557339fee9840ef, + 0xee8c0dfb45ee5d8e, + 0x5da24145464902e1, + 0x1a083bacedaefdd5, + 0xa9267712ee09a2ba, + 0x955cce7fba6103bd, + 0x267282c1b9c65cd2, + 0x61d8f8281221a3e6, + 0xd2f6b4961186fc89, + 0x9f8169ba49a54b33, + 0x2caf25044a02145c, + 0x6b055fede1e5eb68, + 0xd82b1353e242b407, + 0xe451aa3eb62a1500, + 0x577fe680b58d4a6f, + 0x10d59c691e6ab55b, + 0xa3fbd0d71dcdea34, + 0x6820eeb3b6bbf755, + 0xdb0ea20db51ca83a, + 0x9ca4d8e41efb570e, + 0x2f8a945a1d5c0861, + 0x13f02d374934a966, + 0xa0de61894a93f609, + 0xe7741b60e174093d, + 0x545a57dee2d35652, + 0xe21ac88218962d7a, + 0x5134843c1b317215, + 0x169efed5b0d68d21, + 0xa5b0b26bb371d24e, + 0x99ca0b06e7197349, + 0x2ae447b8e4be2c26, + 0x6d4e3d514f59d312, + 0xde6071ef4cfe8c7d, + 0x15bb4f8be788911c, + 0xa6950335e42fce73, + 0xe13f79dc4fc83147, + 0x521135624c6f6e28, + 0x6e6b8c0f1807cf2f, + 0xdd45c0b11ba09040, + 0x9aefba58b0476f74, + 0x29c1f6e6b3e0301b, + 0xc96c5795d7870f42, + 0x7a421b2bd420502d, + 0x3de861c27fc7af19, + 0x8ec62d7c7c60f076, + 0xb2bc941128085171, + 0x192d8af2baf0e1e, + 0x4638a2468048f12a, + 0xf516eef883efae45, + 0x3ecdd09c2899b324, + 0x8de39c222b3eec4b, + 0xca49e6cb80d9137f, + 0x7967aa75837e4c10, + 0x451d1318d716ed17, + 0xf6335fa6d4b1b278, + 0xb199254f7f564d4c, + 0x2b769f17cf11223, + 0xb4f7f6ad86b4690b, + 0x7d9ba1385133664, + 0x4073c0fa2ef4c950, + 0xf35d8c442d53963f, + 0xcf273529793b3738, + 0x7c0979977a9c6857, + 0x3ba3037ed17b9763, + 0x888d4fc0d2dcc80c, + 0x435671a479aad56d, + 0xf0783d1a7a0d8a02, + 0xb7d247f3d1ea7536, + 0x4fc0b4dd24d2a59, + 0x3886b22086258b5e, + 0x8ba8fe9e8582d431, + 0xcc0284772e652b05, + 0x7f2cc8c92dc2746a, + 0x325b15e575e1c3d0, + 0x8175595b76469cbf, + 0xc6df23b2dda1638b, + 0x75f16f0cde063ce4, + 0x498bd6618a6e9de3, + 0xfaa59adf89c9c28c, + 0xbd0fe036222e3db8, + 0xe21ac88218962d7, + 0xc5fa92ec8aff7fb6, + 0x76d4de52895820d9, + 0x317ea4bb22bfdfed, + 0x8250e80521188082, + 0xbe2a516875702185, + 0xd041dd676d77eea, + 0x4aae673fdd3081de, + 0xf9802b81de97deb1, + 0x4fc0b4dd24d2a599, + 0xfceef8632775faf6, + 0xbb44828a8c9205c2, + 0x86ace348f355aad, + 0x34107759db5dfbaa, + 0x873e3be7d8faa4c5, + 0xc094410e731d5bf1, + 0x73ba0db070ba049e, + 0xb86133d4dbcc19ff, + 0xb4f7f6ad86b4690, + 0x4ce50583738cb9a4, + 0xffcb493d702be6cb, + 0xc3b1f050244347cc, + 0x709fbcee27e418a3, + 0x3735c6078c03e797, + 0x841b8ab98fa4b8f8, + 0xadda7c5f3c4488e3, + 0x1ef430e13fe3d78c, + 0x595e4a08940428b8, + 0xea7006b697a377d7, + 0xd60abfdbc3cbd6d0, + 0x6524f365c06c89bf, + 0x228e898c6b8b768b, + 0x91a0c532682c29e4, + 0x5a7bfb56c35a3485, + 0xe955b7e8c0fd6bea, + 0xaeffcd016b1a94de, + 0x1dd181bf68bdcbb1, + 0x21ab38d23cd56ab6, + 0x9285746c3f7235d9, + 0xd52f0e859495caed, + 0x6601423b97329582, + 0xd041dd676d77eeaa, + 0x636f91d96ed0b1c5, + 0x24c5eb30c5374ef1, + 0x97eba78ec690119e, + 0xab911ee392f8b099, + 0x18bf525d915feff6, + 0x5f1528b43ab810c2, + 0xec3b640a391f4fad, + 0x27e05a6e926952cc, + 0x94ce16d091ce0da3, + 0xd3646c393a29f297, + 0x604a2087398eadf8, + 0x5c3099ea6de60cff, + 0xef1ed5546e415390, + 0xa8b4afbdc5a6aca4, + 0x1b9ae303c601f3cb, + 0x56ed3e2f9e224471, + 0xe5c372919d851b1e, + 0xa26908783662e42a, + 0x114744c635c5bb45, + 0x2d3dfdab61ad1a42, + 0x9e13b115620a452d, + 0xd9b9cbfcc9edba19, + 0x6a978742ca4ae576, + 0xa14cb926613cf817, + 0x1262f598629ba778, + 0x55c88f71c97c584c, + 0xe6e6c3cfcadb0723, + 0xda9c7aa29eb3a624, + 0x69b2361c9d14f94b, + 0x2e184cf536f3067f, + 0x9d36004b35545910, + 0x2b769f17cf112238, + 0x9858d3a9ccb67d57, + 0xdff2a94067518263, + 0x6cdce5fe64f6dd0c, + 0x50a65c93309e7c0b, + 0xe388102d33392364, + 0xa4226ac498dedc50, + 0x170c267a9b79833f, + 0xdcd7181e300f9e5e, + 0x6ff954a033a8c131, + 0x28532e49984f3e05, + 0x9b7d62f79be8616a, + 0xa707db9acf80c06d, + 0x14299724cc279f02, + 0x5383edcd67c06036, + 0xe0ada17364673f59, + ], + [ + 0, + 0x54e979925cd0f10d, + 0xa9d2f324b9a1e21a, + 0xfd3b8ab6e5711317, + 0xc17d4962dc4ddab1, + 0x959430f0809d2bbc, + 0x68afba4665ec38ab, + 0x3c46c3d4393cc9a6, + 0x10223dee1795abe7, + 0x44cb447c4b455aea, + 0xb9f0cecaae3449fd, + 0xed19b758f2e4b8f0, + 0xd15f748ccbd87156, + 0x85b60d1e9708805b, + 0x788d87a87279934c, + 0x2c64fe3a2ea96241, + 0x20447bdc2f2b57ce, + 0x74ad024e73fba6c3, + 0x899688f8968ab5d4, + 0xdd7ff16aca5a44d9, + 0xe13932bef3668d7f, + 0xb5d04b2cafb67c72, + 0x48ebc19a4ac76f65, + 0x1c02b80816179e68, + 0x3066463238befc29, + 0x648f3fa0646e0d24, + 0x99b4b516811f1e33, + 0xcd5dcc84ddcfef3e, + 0xf11b0f50e4f32698, + 0xa5f276c2b823d795, + 0x58c9fc745d52c482, + 0xc2085e60182358f, + 0x4088f7b85e56af9c, + 0x14618e2a02865e91, + 0xe95a049ce7f74d86, + 0xbdb37d0ebb27bc8b, + 0x81f5beda821b752d, + 0xd51cc748decb8420, + 0x28274dfe3bba9737, + 0x7cce346c676a663a, + 0x50aaca5649c3047b, + 0x443b3c41513f576, + 0xf9783972f062e661, + 0xad9140e0acb2176c, + 0x91d78334958edeca, + 0xc53efaa6c95e2fc7, + 0x380570102c2f3cd0, + 0x6cec098270ffcddd, + 0x60cc8c64717df852, + 0x3425f5f62dad095f, + 0xc91e7f40c8dc1a48, + 0x9df706d2940ceb45, + 0xa1b1c506ad3022e3, + 0xf558bc94f1e0d3ee, + 0x86336221491c0f9, + 0x5c8a4fb0484131f4, + 0x70eeb18a66e853b5, + 0x2407c8183a38a2b8, + 0xd93c42aedf49b1af, + 0x8dd53b3c839940a2, + 0xb193f8e8baa58904, + 0xe57a817ae6757809, + 0x18410bcc03046b1e, + 0x4ca8725e5fd49a13, + 0x8111ef70bcad5f38, + 0xd5f896e2e07dae35, + 0x28c31c54050cbd22, + 0x7c2a65c659dc4c2f, + 0x406ca61260e08589, + 0x1485df803c307484, + 0xe9be5536d9416793, + 0xbd572ca48591969e, + 0x9133d29eab38f4df, + 0xc5daab0cf7e805d2, + 0x38e121ba129916c5, + 0x6c0858284e49e7c8, + 0x504e9bfc77752e6e, + 0x4a7e26e2ba5df63, + 0xf99c68d8ced4cc74, + 0xad75114a92043d79, + 0xa15594ac938608f6, + 0xf5bced3ecf56f9fb, + 0x88767882a27eaec, + 0x5c6e1e1a76f71be1, + 0x6028ddce4fcbd247, + 0x34c1a45c131b234a, + 0xc9fa2eeaf66a305d, + 0x9d135778aabac150, + 0xb177a9428413a311, + 0xe59ed0d0d8c3521c, + 0x18a55a663db2410b, + 0x4c4c23f46162b006, + 0x700ae020585e79a0, + 0x24e399b2048e88ad, + 0xd9d81304e1ff9bba, + 0x8d316a96bd2f6ab7, + 0xc19918c8e2fbf0a4, + 0x9570615abe2b01a9, + 0x684bebec5b5a12be, + 0x3ca2927e078ae3b3, + 0xe451aa3eb62a15, + 0x540d28386266db18, + 0xa936a28e8717c80f, + 0xfddfdb1cdbc73902, + 0xd1bb2526f56e5b43, + 0x85525cb4a9beaa4e, + 0x7869d6024ccfb959, + 0x2c80af90101f4854, + 0x10c66c44292381f2, + 0x442f15d675f370ff, + 0xb9149f60908263e8, + 0xedfde6f2cc5292e5, + 0xe1dd6314cdd0a76a, + 0xb5341a8691005667, + 0x480f903074714570, + 0x1ce6e9a228a1b47d, + 0x20a02a76119d7ddb, + 0x744953e44d4d8cd6, + 0x8972d952a83c9fc1, + 0xdd9ba0c0f4ec6ecc, + 0xf1ff5efada450c8d, + 0xa51627688695fd80, + 0x582dadde63e4ee97, + 0xcc4d44c3f341f9a, + 0x308217980608d63c, + 0x646b6e0a5ad82731, + 0x9950e4bcbfa93426, + 0xcdb99d2ee379c52b, + 0x90fb71cad654a0f5, + 0xc41208588a8451f8, + 0x392982ee6ff542ef, + 0x6dc0fb7c3325b3e2, + 0x518638a80a197a44, + 0x56f413a56c98b49, + 0xf854cb8cb3b8985e, + 0xacbdb21eef686953, + 0x80d94c24c1c10b12, + 0xd43035b69d11fa1f, + 0x290bbf007860e908, + 0x7de2c69224b01805, + 0x41a405461d8cd1a3, + 0x154d7cd4415c20ae, + 0xe876f662a42d33b9, + 0xbc9f8ff0f8fdc2b4, + 0xb0bf0a16f97ff73b, + 0xe4567384a5af0636, + 0x196df93240de1521, + 0x4d8480a01c0ee42c, + 0x71c2437425322d8a, + 0x252b3ae679e2dc87, + 0xd810b0509c93cf90, + 0x8cf9c9c2c0433e9d, + 0xa09d37f8eeea5cdc, + 0xf4744e6ab23aadd1, + 0x94fc4dc574bbec6, + 0x5da6bd4e0b9b4fcb, + 0x61e07e9a32a7866d, + 0x350907086e777760, + 0xc8328dbe8b066477, + 0x9cdbf42cd7d6957a, + 0xd073867288020f69, + 0x849affe0d4d2fe64, + 0x79a1755631a3ed73, + 0x2d480cc46d731c7e, + 0x110ecf10544fd5d8, + 0x45e7b682089f24d5, + 0xb8dc3c34edee37c2, + 0xec3545a6b13ec6cf, + 0xc051bb9c9f97a48e, + 0x94b8c20ec3475583, + 0x698348b826364694, + 0x3d6a312a7ae6b799, + 0x12cf2fe43da7e3f, + 0x55c58b6c1f0a8f32, + 0xa8fe01dafa7b9c25, + 0xfc177848a6ab6d28, + 0xf037fdaea72958a7, + 0xa4de843cfbf9a9aa, + 0x59e50e8a1e88babd, + 0xd0c771842584bb0, + 0x314ab4cc7b648216, + 0x65a3cd5e27b4731b, + 0x989847e8c2c5600c, + 0xcc713e7a9e159101, + 0xe015c040b0bcf340, + 0xb4fcb9d2ec6c024d, + 0x49c73364091d115a, + 0x1d2e4af655cde057, + 0x216889226cf129f1, + 0x7581f0b03021d8fc, + 0x88ba7a06d550cbeb, + 0xdc53039489803ae6, + 0x11ea9eba6af9ffcd, + 0x4503e72836290ec0, + 0xb8386d9ed3581dd7, + 0xecd1140c8f88ecda, + 0xd097d7d8b6b4257c, + 0x847eae4aea64d471, + 0x794524fc0f15c766, + 0x2dac5d6e53c5366b, + 0x1c8a3547d6c542a, + 0x5521dac621bca527, + 0xa81a5070c4cdb630, + 0xfcf329e2981d473d, + 0xc0b5ea36a1218e9b, + 0x945c93a4fdf17f96, + 0x6967191218806c81, + 0x3d8e608044509d8c, + 0x31aee56645d2a803, + 0x65479cf41902590e, + 0x987c1642fc734a19, + 0xcc956fd0a0a3bb14, + 0xf0d3ac04999f72b2, + 0xa43ad596c54f83bf, + 0x59015f20203e90a8, + 0xde826b27cee61a5, + 0x218cd888524703e4, + 0x7565a11a0e97f2e9, + 0x885e2bacebe6e1fe, + 0xdcb7523eb73610f3, + 0xe0f191ea8e0ad955, + 0xb418e878d2da2858, + 0x492362ce37ab3b4f, + 0x1dca1b5c6b7bca42, + 0x5162690234af5051, + 0x58b1090687fa15c, + 0xf8b09a268d0eb24b, + 0xac59e3b4d1de4346, + 0x901f2060e8e28ae0, + 0xc4f659f2b4327bed, + 0x39cdd344514368fa, + 0x6d24aad60d9399f7, + 0x414054ec233afbb6, + 0x15a92d7e7fea0abb, + 0xe892a7c89a9b19ac, + 0xbc7bde5ac64be8a1, + 0x803d1d8eff772107, + 0xd4d4641ca3a7d00a, + 0x29efeeaa46d6c31d, + 0x7d0697381a063210, + 0x712612de1b84079f, + 0x25cf6b4c4754f692, + 0xd8f4e1faa225e585, + 0x8c1d9868fef51488, + 0xb05b5bbcc7c9dd2e, + 0xe4b2222e9b192c23, + 0x1989a8987e683f34, + 0x4d60d10a22b8ce39, + 0x61042f300c11ac78, + 0x35ed56a250c15d75, + 0xc8d6dc14b5b04e62, + 0x9c3fa586e960bf6f, + 0xa0796652d05c76c9, + 0xf4901fc08c8c87c4, + 0x9ab957669fd94d3, + 0x5d42ece4352d65de, + ], + [ + 0, + 0x3f0be14a916a6dcb, + 0x7e17c29522d4db96, + 0x411c23dfb3beb65d, + 0xfc2f852a45a9b72c, + 0xc3246460d4c3dae7, + 0x823847bf677d6cba, + 0xbd33a6f5f6170171, + 0x6a87a57f245d70dd, + 0x558c4435b5371d16, + 0x149067ea0689ab4b, + 0x2b9b86a097e3c680, + 0x96a8205561f4c7f1, + 0xa9a3c11ff09eaa3a, + 0xe8bfe2c043201c67, + 0xd7b4038ad24a71ac, + 0xd50f4afe48bae1ba, + 0xea04abb4d9d08c71, + 0xab18886b6a6e3a2c, + 0x94136921fb0457e7, + 0x2920cfd40d135696, + 0x162b2e9e9c793b5d, + 0x57370d412fc78d00, + 0x683cec0bbeade0cb, + 0xbf88ef816ce79167, + 0x80830ecbfd8dfcac, + 0xc19f2d144e334af1, + 0xfe94cc5edf59273a, + 0x43a76aab294e264b, + 0x7cac8be1b8244b80, + 0x3db0a83e0b9afddd, + 0x2bb49749af09016, + 0x38c63ad73e7bddf1, + 0x7cddb9daf11b03a, + 0x46d1f8421caf0667, + 0x79da19088dc56bac, + 0xc4e9bffd7bd26add, + 0xfbe25eb7eab80716, + 0xbafe7d685906b14b, + 0x85f59c22c86cdc80, + 0x52419fa81a26ad2c, + 0x6d4a7ee28b4cc0e7, + 0x2c565d3d38f276ba, + 0x135dbc77a9981b71, + 0xae6e1a825f8f1a00, + 0x9165fbc8cee577cb, + 0xd079d8177d5bc196, + 0xef72395dec31ac5d, + 0xedc9702976c13c4b, + 0xd2c29163e7ab5180, + 0x93deb2bc5415e7dd, + 0xacd553f6c57f8a16, + 0x11e6f50333688b67, + 0x2eed1449a202e6ac, + 0x6ff1379611bc50f1, + 0x50fad6dc80d63d3a, + 0x874ed556529c4c96, + 0xb845341cc3f6215d, + 0xf95917c370489700, + 0xc652f689e122facb, + 0x7b61507c1735fbba, + 0x446ab136865f9671, + 0x57692e935e1202c, + 0x3a7d73a3a48b4de7, + 0x718c75ae7cf7bbe2, + 0x4e8794e4ed9dd629, + 0xf9bb73b5e236074, + 0x30905671cf490dbf, + 0x8da3f084395e0cce, + 0xb2a811cea8346105, + 0xf3b432111b8ad758, + 0xccbfd35b8ae0ba93, + 0x1b0bd0d158aacb3f, + 0x2400319bc9c0a6f4, + 0x651c12447a7e10a9, + 0x5a17f30eeb147d62, + 0xe72455fb1d037c13, + 0xd82fb4b18c6911d8, + 0x9933976e3fd7a785, + 0xa6387624aebdca4e, + 0xa4833f50344d5a58, + 0x9b88de1aa5273793, + 0xda94fdc5169981ce, + 0xe59f1c8f87f3ec05, + 0x58acba7a71e4ed74, + 0x67a75b30e08e80bf, + 0x26bb78ef533036e2, + 0x19b099a5c25a5b29, + 0xce049a2f10102a85, + 0xf10f7b65817a474e, + 0xb01358ba32c4f113, + 0x8f18b9f0a3ae9cd8, + 0x322b1f0555b99da9, + 0xd20fe4fc4d3f062, + 0x4c3cdd90776d463f, + 0x73373cdae6072bf4, + 0x494a4f79428c6613, + 0x7641ae33d3e60bd8, + 0x375d8dec6058bd85, + 0x8566ca6f132d04e, + 0xb565ca530725d13f, + 0x8a6e2b19964fbcf4, + 0xcb7208c625f10aa9, + 0xf479e98cb49b6762, + 0x23cdea0666d116ce, + 0x1cc60b4cf7bb7b05, + 0x5dda28934405cd58, + 0x62d1c9d9d56fa093, + 0xdfe26f2c2378a1e2, + 0xe0e98e66b212cc29, + 0xa1f5adb901ac7a74, + 0x9efe4cf390c617bf, + 0x9c4505870a3687a9, + 0xa34ee4cd9b5cea62, + 0xe252c71228e25c3f, + 0xdd592658b98831f4, + 0x606a80ad4f9f3085, + 0x5f6161e7def55d4e, + 0x1e7d42386d4beb13, + 0x2176a372fc2186d8, + 0xf6c2a0f82e6bf774, + 0xc9c941b2bf019abf, + 0x88d5626d0cbf2ce2, + 0xb7de83279dd54129, + 0xaed25d26bc24058, + 0x35e6c498faa82d93, + 0x74fae74749169bce, + 0x4bf1060dd87cf605, + 0xe318eb5cf9ef77c4, + 0xdc130a1668851a0f, + 0x9d0f29c9db3bac52, + 0xa204c8834a51c199, + 0x1f376e76bc46c0e8, + 0x203c8f3c2d2cad23, + 0x6120ace39e921b7e, + 0x5e2b4da90ff876b5, + 0x899f4e23ddb20719, + 0xb694af694cd86ad2, + 0xf7888cb6ff66dc8f, + 0xc8836dfc6e0cb144, + 0x75b0cb09981bb035, + 0x4abb2a430971ddfe, + 0xba7099cbacf6ba3, + 0x34ace8d62ba50668, + 0x3617a1a2b155967e, + 0x91c40e8203ffbb5, + 0x4800633793814de8, + 0x770b827d02eb2023, + 0xca382488f4fc2152, + 0xf533c5c265964c99, + 0xb42fe61dd628fac4, + 0x8b2407574742970f, + 0x5c9004dd9508e6a3, + 0x639be59704628b68, + 0x2287c648b7dc3d35, + 0x1d8c270226b650fe, + 0xa0bf81f7d0a1518f, + 0x9fb460bd41cb3c44, + 0xdea84362f2758a19, + 0xe1a3a228631fe7d2, + 0xdbded18bc794aa35, + 0xe4d530c156fec7fe, + 0xa5c9131ee54071a3, + 0x9ac2f254742a1c68, + 0x27f154a1823d1d19, + 0x18fab5eb135770d2, + 0x59e69634a0e9c68f, + 0x66ed777e3183ab44, + 0xb15974f4e3c9dae8, + 0x8e5295be72a3b723, + 0xcf4eb661c11d017e, + 0xf045572b50776cb5, + 0x4d76f1dea6606dc4, + 0x727d1094370a000f, + 0x3361334b84b4b652, + 0xc6ad20115dedb99, + 0xed19b758f2e4b8f, + 0x31da7a3f1e442644, + 0x70c659e0adfa9019, + 0x4fcdb8aa3c90fdd2, + 0xf2fe1e5fca87fca3, + 0xcdf5ff155bed9168, + 0x8ce9dccae8532735, + 0xb3e23d8079394afe, + 0x64563e0aab733b52, + 0x5b5ddf403a195699, + 0x1a41fc9f89a7e0c4, + 0x254a1dd518cd8d0f, + 0x9879bb20eeda8c7e, + 0xa7725a6a7fb0e1b5, + 0xe66e79b5cc0e57e8, + 0xd96598ff5d643a23, + 0x92949ef28518cc26, + 0xad9f7fb81472a1ed, + 0xec835c67a7cc17b0, + 0xd388bd2d36a67a7b, + 0x6ebb1bd8c0b17b0a, + 0x51b0fa9251db16c1, + 0x10acd94de265a09c, + 0x2fa73807730fcd57, + 0xf8133b8da145bcfb, + 0xc718dac7302fd130, + 0x8604f9188391676d, + 0xb90f185212fb0aa6, + 0x43cbea7e4ec0bd7, + 0x3b375fed7586661c, + 0x7a2b7c32c638d041, + 0x45209d785752bd8a, + 0x479bd40ccda22d9c, + 0x789035465cc84057, + 0x398c1699ef76f60a, + 0x687f7d37e1c9bc1, + 0xbbb45126880b9ab0, + 0x84bfb06c1961f77b, + 0xc5a393b3aadf4126, + 0xfaa872f93bb52ced, + 0x2d1c7173e9ff5d41, + 0x121790397895308a, + 0x530bb3e6cb2b86d7, + 0x6c0052ac5a41eb1c, + 0xd133f459ac56ea6d, + 0xee3815133d3c87a6, + 0xaf2436cc8e8231fb, + 0x902fd7861fe85c30, + 0xaa52a425bb6311d7, + 0x9559456f2a097c1c, + 0xd44566b099b7ca41, + 0xeb4e87fa08dda78a, + 0x567d210ffecaa6fb, + 0x6976c0456fa0cb30, + 0x286ae39adc1e7d6d, + 0x176102d04d7410a6, + 0xc0d5015a9f3e610a, + 0xffdee0100e540cc1, + 0xbec2c3cfbdeaba9c, + 0x81c922852c80d757, + 0x3cfa8470da97d626, + 0x3f1653a4bfdbbed, + 0x42ed46e5f8430db0, + 0x7de6a7af6929607b, + 0x7f5deedbf3d9f06d, + 0x40560f9162b39da6, + 0x14a2c4ed10d2bfb, + 0x3e41cd0440674630, + 0x83726bf1b6704741, + 0xbc798abb271a2a8a, + 0xfd65a96494a49cd7, + 0xc26e482e05cef11c, + 0x15da4ba4d78480b0, + 0x2ad1aaee46eeed7b, + 0x6bcd8931f5505b26, + 0x54c6687b643a36ed, + 0xe9f5ce8e922d379c, + 0xd6fe2fc403475a57, + 0x97e20c1bb0f9ec0a, + 0xa8e9ed51219381c1, + ], + [ + 0, + 0x1dee8a5e222ca1dc, + 0x3bdd14bc445943b8, + 0x26339ee26675e264, + 0x77ba297888b28770, + 0x6a54a326aa9e26ac, + 0x4c673dc4ccebc4c8, + 0x5189b79aeec76514, + 0xef7452f111650ee0, + 0xf29ad8af3349af3c, + 0xd4a9464d553c4d58, + 0xc947cc137710ec84, + 0x98ce7b8999d78990, + 0x8520f1d7bbfb284c, + 0xa3136f35dd8eca28, + 0xbefde56bffa26bf4, + 0x4c300ac98dc40345, + 0x51de8097afe8a299, + 0x77ed1e75c99d40fd, + 0x6a03942bebb1e121, + 0x3b8a23b105768435, + 0x2664a9ef275a25e9, + 0x57370d412fc78d, + 0x1db9bd5363036651, + 0xa34458389ca10da5, + 0xbeaad266be8dac79, + 0x98994c84d8f84e1d, + 0x8577c6dafad4efc1, + 0xd4fe714014138ad5, + 0xc910fb1e363f2b09, + 0xef2365fc504ac96d, + 0xf2cdefa2726668b1, + 0x986015931b88068a, + 0x858e9fcd39a4a756, + 0xa3bd012f5fd14532, + 0xbe538b717dfde4ee, + 0xefda3ceb933a81fa, + 0xf234b6b5b1162026, + 0xd4072857d763c242, + 0xc9e9a209f54f639e, + 0x771447620aed086a, + 0x6afacd3c28c1a9b6, + 0x4cc953de4eb44bd2, + 0x5127d9806c98ea0e, + 0xae6e1a825f8f1a, + 0x1d40e444a0732ec6, + 0x3b737aa6c606cca2, + 0x269df0f8e42a6d7e, + 0xd4501f5a964c05cf, + 0xc9be9504b460a413, + 0xef8d0be6d2154677, + 0xf26381b8f039e7ab, + 0xa3ea36221efe82bf, + 0xbe04bc7c3cd22363, + 0x9837229e5aa7c107, + 0x85d9a8c0788b60db, + 0x3b244dab87290b2f, + 0x26cac7f5a505aaf3, + 0xf95917c3704897, + 0x1d17d349e15ce94b, + 0x4c9e64d30f9b8c5f, + 0x5170ee8d2db72d83, + 0x7743706f4bc2cfe7, + 0x6aadfa3169ee6e3b, + 0xa218840d981e1391, + 0xbff60e53ba32b24d, + 0x99c590b1dc475029, + 0x842b1aeffe6bf1f5, + 0xd5a2ad7510ac94e1, + 0xc84c272b3280353d, + 0xee7fb9c954f5d759, + 0xf391339776d97685, + 0x4d6cd6fc897b1d71, + 0x50825ca2ab57bcad, + 0x76b1c240cd225ec9, + 0x6b5f481eef0eff15, + 0x3ad6ff8401c99a01, + 0x273875da23e53bdd, + 0x10beb384590d9b9, + 0x1ce5616667bc7865, + 0xee288ec415da10d4, + 0xf3c6049a37f6b108, + 0xd5f59a785183536c, + 0xc81b102673aff2b0, + 0x9992a7bc9d6897a4, + 0x847c2de2bf443678, + 0xa24fb300d931d41c, + 0xbfa1395efb1d75c0, + 0x15cdc3504bf1e34, + 0x1cb2566b2693bfe8, + 0x3a81c88940e65d8c, + 0x276f42d762cafc50, + 0x76e6f54d8c0d9944, + 0x6b087f13ae213898, + 0x4d3be1f1c854dafc, + 0x50d56bafea787b20, + 0x3a78919e8396151b, + 0x27961bc0a1bab4c7, + 0x1a58522c7cf56a3, + 0x1c4b0f7ce5e3f77f, + 0x4dc2b8e60b24926b, + 0x502c32b8290833b7, + 0x761fac5a4f7dd1d3, + 0x6bf126046d51700f, + 0xd50cc36f92f31bfb, + 0xc8e24931b0dfba27, + 0xeed1d7d3d6aa5843, + 0xf33f5d8df486f99f, + 0xa2b6ea171a419c8b, + 0xbf586049386d3d57, + 0x996bfeab5e18df33, + 0x848574f57c347eef, + 0x76489b570e52165e, + 0x6ba611092c7eb782, + 0x4d958feb4a0b55e6, + 0x507b05b56827f43a, + 0x1f2b22f86e0912e, + 0x1c1c3871a4cc30f2, + 0x3a2fa693c2b9d296, + 0x27c12ccde095734a, + 0x993cc9a61f3718be, + 0x84d243f83d1bb962, + 0xa2e1dd1a5b6e5b06, + 0xbf0f57447942fada, + 0xee86e0de97859fce, + 0xf3686a80b5a93e12, + 0xd55bf462d3dcdc76, + 0xc8b57e3cf1f07daa, + 0xd6e9a7309f3239a7, + 0xcb072d6ebd1e987b, + 0xed34b38cdb6b7a1f, + 0xf0da39d2f947dbc3, + 0xa1538e481780bed7, + 0xbcbd041635ac1f0b, + 0x9a8e9af453d9fd6f, + 0x876010aa71f55cb3, + 0x399df5c18e573747, + 0x24737f9fac7b969b, + 0x240e17dca0e74ff, + 0x1fae6b23e822d523, + 0x4e27dcb906e5b037, + 0x53c956e724c911eb, + 0x75fac80542bcf38f, + 0x6814425b60905253, + 0x9ad9adf912f63ae2, + 0x873727a730da9b3e, + 0xa104b94556af795a, + 0xbcea331b7483d886, + 0xed6384819a44bd92, + 0xf08d0edfb8681c4e, + 0xd6be903dde1dfe2a, + 0xcb501a63fc315ff6, + 0x75adff0803933402, + 0x6843755621bf95de, + 0x4e70ebb447ca77ba, + 0x539e61ea65e6d666, + 0x217d6708b21b372, + 0x1ff95c2ea90d12ae, + 0x39cac2cccf78f0ca, + 0x24244892ed545116, + 0x4e89b2a384ba3f2d, + 0x536738fda6969ef1, + 0x7554a61fc0e37c95, + 0x68ba2c41e2cfdd49, + 0x39339bdb0c08b85d, + 0x24dd11852e241981, + 0x2ee8f674851fbe5, + 0x1f0005396a7d5a39, + 0xa1fde05295df31cd, + 0xbc136a0cb7f39011, + 0x9a20f4eed1867275, + 0x87ce7eb0f3aad3a9, + 0xd647c92a1d6db6bd, + 0xcba943743f411761, + 0xed9add965934f505, + 0xf07457c87b1854d9, + 0x2b9b86a097e3c68, + 0x1f5732342b529db4, + 0x3964acd64d277fd0, + 0x248a26886f0bde0c, + 0x7503911281ccbb18, + 0x68ed1b4ca3e01ac4, + 0x4ede85aec595f8a0, + 0x53300ff0e7b9597c, + 0xedcdea9b181b3288, + 0xf02360c53a379354, + 0xd610fe275c427130, + 0xcbfe74797e6ed0ec, + 0x9a77c3e390a9b5f8, + 0x879949bdb2851424, + 0xa1aad75fd4f0f640, + 0xbc445d01f6dc579c, + 0x74f1233d072c2a36, + 0x691fa96325008bea, + 0x4f2c37814375698e, + 0x52c2bddf6159c852, + 0x34b0a458f9ead46, + 0x1ea5801badb20c9a, + 0x38961ef9cbc7eefe, + 0x257894a7e9eb4f22, + 0x9b8571cc164924d6, + 0x866bfb923465850a, + 0xa05865705210676e, + 0xbdb6ef2e703cc6b2, + 0xec3f58b49efba3a6, + 0xf1d1d2eabcd7027a, + 0xd7e24c08daa2e01e, + 0xca0cc656f88e41c2, + 0x38c129f48ae82973, + 0x252fa3aaa8c488af, + 0x31c3d48ceb16acb, + 0x1ef2b716ec9dcb17, + 0x4f7b008c025aae03, + 0x52958ad220760fdf, + 0x74a614304603edbb, + 0x69489e6e642f4c67, + 0xd7b57b059b8d2793, + 0xca5bf15bb9a1864f, + 0xec686fb9dfd4642b, + 0xf186e5e7fdf8c5f7, + 0xa00f527d133fa0e3, + 0xbde1d8233113013f, + 0x9bd246c15766e35b, + 0x863ccc9f754a4287, + 0xec9136ae1ca42cbc, + 0xf17fbcf03e888d60, + 0xd74c221258fd6f04, + 0xcaa2a84c7ad1ced8, + 0x9b2b1fd69416abcc, + 0x86c59588b63a0a10, + 0xa0f60b6ad04fe874, + 0xbd188134f26349a8, + 0x3e5645f0dc1225c, + 0x1e0bee012fed8380, + 0x383870e3499861e4, + 0x25d6fabd6bb4c038, + 0x745f4d278573a52c, + 0x69b1c779a75f04f0, + 0x4f82599bc12ae694, + 0x526cd3c5e3064748, + 0xa0a13c6791602ff9, + 0xbd4fb639b34c8e25, + 0x9b7c28dbd5396c41, + 0x8692a285f715cd9d, + 0xd71b151f19d2a889, + 0xcaf59f413bfe0955, + 0xecc601a35d8beb31, + 0xf1288bfd7fa74aed, + 0x4fd56e9680052119, + 0x523be4c8a22980c5, + 0x74087a2ac45c62a1, + 0x69e6f074e670c37d, + 0x386f47ee08b7a669, + 0x2581cdb02a9b07b5, + 0x3b253524ceee5d1, + 0x1e5cd90c6ec2440d, + ], +]; +#[inline] +unsafe fn lzma_crc64_generic(mut buf: *const u8, mut size: size_t, mut crc: u64) -> u64 { + crc = !crc; + if size > 4 { + while buf as uintptr_t & 3 as uintptr_t != 0 { + crc = lzma_crc64_table[0][(*buf as u64 ^ crc & 0xff as u64) as usize] ^ crc >> 8; + buf = buf.offset(1); + size -= 1; + } + let limit: *const u8 = buf.offset((size & !(3)) as isize); + size &= 3; + while buf < limit { + let tmp: u32 = crc as u32 ^ aligned_read32ne(buf) as u32; + buf = buf.offset(4); + crc = lzma_crc64_table[3][(tmp & 0xff) as usize] + ^ lzma_crc64_table[2][(tmp >> 8 & 0xff) as usize] + ^ crc >> 32 + ^ lzma_crc64_table[1][(tmp >> 16 & 0xff) as usize] + ^ lzma_crc64_table[0][(tmp >> 24) as usize]; + } + } + while size > 0 { + crc = lzma_crc64_table[0][(*buf as u64 ^ crc & 0xff as u64) as usize] ^ crc >> 8; + buf = buf.offset(1); + size -= 1; + } + !crc +} +pub unsafe fn lzma_crc64(buf: *const u8, size: size_t, crc: u64) -> u64 { + lzma_crc64_generic(buf, size, crc) +} diff --git a/liblzma-rs/src/check/mod.rs b/liblzma-rs/src/check/mod.rs new file mode 100644 index 00000000..e9d694a4 --- /dev/null +++ b/liblzma-rs/src/check/mod.rs @@ -0,0 +1,4 @@ +pub mod check; +pub mod crc32_fast; +pub mod crc64_fast; +pub mod sha256; diff --git a/liblzma-rs/src/check/sha256.rs b/liblzma-rs/src/check/sha256.rs new file mode 100644 index 00000000..f9b8de44 --- /dev/null +++ b/liblzma-rs/src/check/sha256.rs @@ -0,0 +1,601 @@ +use crate::types::*; +#[inline] +extern "C" fn rotr_32(num: u32, amount: c_uint) -> u32 { + num >> amount | num << 32u32.wrapping_sub(amount) +} +static mut SHA256_K: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0xfc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x6ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; +unsafe fn transform(state: *mut u32, data: *const u32) { + let mut W: [u32; 16] = [0; 16]; + let mut T: [u32; 8] = [0; 8]; + core::ptr::copy_nonoverlapping( + state as *const u8, + ::core::ptr::addr_of_mut!(T) as *mut u8, + core::mem::size_of::<[u32; 8]>(), + ); + W[0] = (*data & 0xff) << 24 + | (*data & 0xff00) << 8 + | (*data & 0xff0000) >> 8 + | (*data & 0xff000000) >> 24; + T[7] = T[7].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 14), 5), 6) + .wrapping_add(T[6] ^ T[4] & (T[5] ^ T[6])) + .wrapping_add(SHA256_K[0]) + .wrapping_add(W[0]), + ); + T[3] = T[3].wrapping_add(T[7]); + T[7] = T[7].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 9), 11), 2) + .wrapping_add((T[0] & (T[1] ^ T[2])).wrapping_add(T[1] & T[2])), + ); + W[1] = (*data.offset(1) & 0xff) << 24 + | (*data.offset(1) & 0xff00) << 8 + | (*data.offset(1) & 0xff0000) >> 8 + | (*data.offset(1) & 0xff000000) >> 24; + T[6] = T[6].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 14), 5), 6) + .wrapping_add(T[5] ^ T[3] & (T[4] ^ T[5])) + .wrapping_add(SHA256_K[1]) + .wrapping_add(W[1]), + ); + T[2] = T[2].wrapping_add(T[6]); + T[6] = T[6].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 9), 11), 2) + .wrapping_add((T[7] & (T[0] ^ T[1])).wrapping_add(T[0] & T[1])), + ); + W[2] = (*data.offset(2) & 0xff) << 24 + | (*data.offset(2) & 0xff00) << 8 + | (*data.offset(2) & 0xff0000) >> 8 + | (*data.offset(2) & 0xff000000) >> 24; + T[5] = T[5].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 14), 5), 6) + .wrapping_add(T[4] ^ T[2] & (T[3] ^ T[4])) + .wrapping_add(SHA256_K[2]) + .wrapping_add(W[2]), + ); + T[1] = T[1].wrapping_add(T[5]); + T[5] = T[5].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 9), 11), 2) + .wrapping_add((T[6] & (T[7] ^ T[0])).wrapping_add(T[7] & T[0])), + ); + W[3] = (*data.offset(3) & 0xff) << 24 + | (*data.offset(3) & 0xff00) << 8 + | (*data.offset(3) & 0xff0000) >> 8 + | (*data.offset(3) & 0xff000000) >> 24; + T[4] = T[4].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 14), 5), 6) + .wrapping_add(T[3] ^ T[1] & (T[2] ^ T[3])) + .wrapping_add(SHA256_K[3]) + .wrapping_add(W[3]), + ); + T[0] = T[0].wrapping_add(T[4]); + T[4] = T[4].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 9), 11), 2) + .wrapping_add((T[5] & (T[6] ^ T[7])).wrapping_add(T[6] & T[7])), + ); + W[4] = (*data.offset(4) & 0xff) << 24 + | (*data.offset(4) & 0xff00) << 8 + | (*data.offset(4) & 0xff0000) >> 8 + | (*data.offset(4) & 0xff000000) >> 24; + T[3] = T[3].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 14), 5), 6) + .wrapping_add(T[2] ^ T[0] & (T[1] ^ T[2])) + .wrapping_add(SHA256_K[4]) + .wrapping_add(W[4]), + ); + T[7] = T[7].wrapping_add(T[3]); + T[3] = T[3].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 9), 11), 2) + .wrapping_add((T[4] & (T[5] ^ T[6])).wrapping_add(T[5] & T[6])), + ); + W[5] = (*data.offset(5) & 0xff) << 24 + | (*data.offset(5) & 0xff00) << 8 + | (*data.offset(5) & 0xff0000) >> 8 + | (*data.offset(5) & 0xff000000) >> 24; + T[2] = T[2].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 14), 5), 6) + .wrapping_add(T[1] ^ T[7] & (T[0] ^ T[1])) + .wrapping_add(SHA256_K[5]) + .wrapping_add(W[5]), + ); + T[6] = T[6].wrapping_add(T[2]); + T[2] = T[2].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 9), 11), 2) + .wrapping_add((T[3] & (T[4] ^ T[5])).wrapping_add(T[4] & T[5])), + ); + W[6] = (*data.offset(6) & 0xff) << 24 + | (*data.offset(6) & 0xff00) << 8 + | (*data.offset(6) & 0xff0000) >> 8 + | (*data.offset(6) & 0xff000000) >> 24; + T[1] = T[1].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 14), 5), 6) + .wrapping_add(T[0] ^ T[6] & (T[7] ^ T[0])) + .wrapping_add(SHA256_K[6]) + .wrapping_add(W[6]), + ); + T[5] = T[5].wrapping_add(T[1]); + T[1] = T[1].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 9), 11), 2) + .wrapping_add((T[2] & (T[3] ^ T[4])).wrapping_add(T[3] & T[4])), + ); + W[7] = (*data.offset(7) & 0xff) << 24 + | (*data.offset(7) & 0xff00) << 8 + | (*data.offset(7) & 0xff0000) >> 8 + | (*data.offset(7) & 0xff000000) >> 24; + T[0] = T[0].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 14), 5), 6) + .wrapping_add(T[7] ^ T[5] & (T[6] ^ T[7])) + .wrapping_add(SHA256_K[7]) + .wrapping_add(W[7]), + ); + T[4] = T[4].wrapping_add(T[0]); + T[0] = T[0].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 9), 11), 2) + .wrapping_add((T[1] & (T[2] ^ T[3])).wrapping_add(T[2] & T[3])), + ); + W[8] = (*data.offset(8) & 0xff) << 24 + | (*data.offset(8) & 0xff00) << 8 + | (*data.offset(8) & 0xff0000) >> 8 + | (*data.offset(8) & 0xff000000) >> 24; + T[7] = T[7].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 14), 5), 6) + .wrapping_add(T[6] ^ T[4] & (T[5] ^ T[6])) + .wrapping_add(SHA256_K[8]) + .wrapping_add(W[8]), + ); + T[3] = T[3].wrapping_add(T[7]); + T[7] = T[7].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 9), 11), 2) + .wrapping_add((T[0] & (T[1] ^ T[2])).wrapping_add(T[1] & T[2])), + ); + W[9] = (*data.offset(9) & 0xff) << 24 + | (*data.offset(9) & 0xff00) << 8 + | (*data.offset(9) & 0xff0000) >> 8 + | (*data.offset(9) & 0xff000000) >> 24; + T[6] = T[6].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 14), 5), 6) + .wrapping_add(T[5] ^ T[3] & (T[4] ^ T[5])) + .wrapping_add(SHA256_K[9]) + .wrapping_add(W[9]), + ); + T[2] = T[2].wrapping_add(T[6]); + T[6] = T[6].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 9), 11), 2) + .wrapping_add((T[7] & (T[0] ^ T[1])).wrapping_add(T[0] & T[1])), + ); + W[10] = (*data.offset(10) & 0xff) << 24 + | (*data.offset(10) & 0xff00) << 8 + | (*data.offset(10) & 0xff0000) >> 8 + | (*data.offset(10) & 0xff000000) >> 24; + T[5] = T[5].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 14), 5), 6) + .wrapping_add(T[4] ^ T[2] & (T[3] ^ T[4])) + .wrapping_add(SHA256_K[10]) + .wrapping_add(W[10]), + ); + T[1] = T[1].wrapping_add(T[5]); + T[5] = T[5].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 9), 11), 2) + .wrapping_add((T[6] & (T[7] ^ T[0])).wrapping_add(T[7] & T[0])), + ); + W[11] = (*data.offset(11) & 0xff) << 24 + | (*data.offset(11) & 0xff00) << 8 + | (*data.offset(11) & 0xff0000) >> 8 + | (*data.offset(11) & 0xff000000) >> 24; + T[4] = T[4].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 14), 5), 6) + .wrapping_add(T[3] ^ T[1] & (T[2] ^ T[3])) + .wrapping_add(SHA256_K[11]) + .wrapping_add(W[11]), + ); + T[0] = T[0].wrapping_add(T[4]); + T[4] = T[4].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 9), 11), 2) + .wrapping_add((T[5] & (T[6] ^ T[7])).wrapping_add(T[6] & T[7])), + ); + W[12] = (*data.offset(12) & 0xff) << 24 + | (*data.offset(12) & 0xff00) << 8 + | (*data.offset(12) & 0xff0000) >> 8 + | (*data.offset(12) & 0xff000000) >> 24; + T[3] = T[3].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 14), 5), 6) + .wrapping_add(T[2] ^ T[0] & (T[1] ^ T[2])) + .wrapping_add(SHA256_K[12]) + .wrapping_add(W[12]), + ); + T[7] = T[7].wrapping_add(T[3]); + T[3] = T[3].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 9), 11), 2) + .wrapping_add((T[4] & (T[5] ^ T[6])).wrapping_add(T[5] & T[6])), + ); + W[13] = (*data.offset(13) & 0xff) << 24 + | (*data.offset(13) & 0xff00) << 8 + | (*data.offset(13) & 0xff0000) >> 8 + | (*data.offset(13) & 0xff000000) >> 24; + T[2] = T[2].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 14), 5), 6) + .wrapping_add(T[1] ^ T[7] & (T[0] ^ T[1])) + .wrapping_add(SHA256_K[13]) + .wrapping_add(W[13]), + ); + T[6] = T[6].wrapping_add(T[2]); + T[2] = T[2].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 9), 11), 2) + .wrapping_add((T[3] & (T[4] ^ T[5])).wrapping_add(T[4] & T[5])), + ); + W[14] = (*data.offset(14) & 0xff) << 24 + | (*data.offset(14) & 0xff00) << 8 + | (*data.offset(14) & 0xff0000) >> 8 + | (*data.offset(14) & 0xff000000) >> 24; + T[1] = T[1].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 14), 5), 6) + .wrapping_add(T[0] ^ T[6] & (T[7] ^ T[0])) + .wrapping_add(SHA256_K[14]) + .wrapping_add(W[14]), + ); + T[5] = T[5].wrapping_add(T[1]); + T[1] = T[1].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 9), 11), 2) + .wrapping_add((T[2] & (T[3] ^ T[4])).wrapping_add(T[3] & T[4])), + ); + W[15] = (*data.offset(15) & 0xff) << 24 + | (*data.offset(15) & 0xff00) << 8 + | (*data.offset(15) & 0xff0000) >> 8 + | (*data.offset(15) & 0xff000000) >> 24; + T[0] = T[0].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 14), 5), 6) + .wrapping_add(T[7] ^ T[5] & (T[6] ^ T[7])) + .wrapping_add(SHA256_K[15]) + .wrapping_add(W[15]), + ); + T[4] = T[4].wrapping_add(T[0]); + T[0] = T[0].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 9), 11), 2) + .wrapping_add((T[1] & (T[2] ^ T[3])).wrapping_add(T[2] & T[3])), + ); + let mut j: c_uint = 16; + while j < 64 { + W[0] = W[0].wrapping_add( + (rotr_32(W[14] ^ rotr_32(W[14], 2), 17) ^ W[14] >> 10) + .wrapping_add(W[9]) + .wrapping_add(rotr_32(W[1] ^ rotr_32(W[1], 11), 7) ^ W[1] >> 3), + ); + T[7] = T[7].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 14), 5), 6) + .wrapping_add(T[6] ^ T[4] & (T[5] ^ T[6])) + .wrapping_add(SHA256_K[0u32.wrapping_add(j) as usize]) + .wrapping_add(W[0]), + ); + T[3] = T[3].wrapping_add(T[7]); + T[7] = T[7].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 9), 11), 2) + .wrapping_add((T[0] & (T[1] ^ T[2])).wrapping_add(T[1] & T[2])), + ); + W[1] = W[1].wrapping_add( + (rotr_32(W[15] ^ rotr_32(W[15], 2), 17) ^ W[15] >> 10) + .wrapping_add(W[10]) + .wrapping_add(rotr_32(W[2] ^ rotr_32(W[2], 11), 7) ^ W[2] >> 3), + ); + T[6] = T[6].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 14), 5), 6) + .wrapping_add(T[5] ^ T[3] & (T[4] ^ T[5])) + .wrapping_add(SHA256_K[1u32.wrapping_add(j) as usize]) + .wrapping_add(W[1]), + ); + T[2] = T[2].wrapping_add(T[6]); + T[6] = T[6].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 9), 11), 2) + .wrapping_add((T[7] & (T[0] ^ T[1])).wrapping_add(T[0] & T[1])), + ); + W[2] = W[2].wrapping_add( + (rotr_32(W[0] ^ rotr_32(W[0], 2), 17) ^ W[0] >> 10) + .wrapping_add(W[11]) + .wrapping_add(rotr_32(W[3] ^ rotr_32(W[3], 11), 7) ^ W[3] >> 3), + ); + T[5] = T[5].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 14), 5), 6) + .wrapping_add(T[4] ^ T[2] & (T[3] ^ T[4])) + .wrapping_add(SHA256_K[2u32.wrapping_add(j) as usize]) + .wrapping_add(W[2]), + ); + T[1] = T[1].wrapping_add(T[5]); + T[5] = T[5].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 9), 11), 2) + .wrapping_add((T[6] & (T[7] ^ T[0])).wrapping_add(T[7] & T[0])), + ); + W[3] = W[3].wrapping_add( + (rotr_32(W[1] ^ rotr_32(W[1], 2), 17) ^ W[1] >> 10) + .wrapping_add(W[12]) + .wrapping_add(rotr_32(W[4] ^ rotr_32(W[4], 11), 7) ^ W[4] >> 3), + ); + T[4] = T[4].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 14), 5), 6) + .wrapping_add(T[3] ^ T[1] & (T[2] ^ T[3])) + .wrapping_add(SHA256_K[3u32.wrapping_add(j) as usize]) + .wrapping_add(W[3]), + ); + T[0] = T[0].wrapping_add(T[4]); + T[4] = T[4].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 9), 11), 2) + .wrapping_add((T[5] & (T[6] ^ T[7])).wrapping_add(T[6] & T[7])), + ); + W[4] = W[4].wrapping_add( + (rotr_32(W[2] ^ rotr_32(W[2], 2), 17) ^ W[2] >> 10) + .wrapping_add(W[13]) + .wrapping_add(rotr_32(W[5] ^ rotr_32(W[5], 11), 7) ^ W[5] >> 3), + ); + T[3] = T[3].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 14), 5), 6) + .wrapping_add(T[2] ^ T[0] & (T[1] ^ T[2])) + .wrapping_add(SHA256_K[4u32.wrapping_add(j) as usize]) + .wrapping_add(W[4]), + ); + T[7] = T[7].wrapping_add(T[3]); + T[3] = T[3].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 9), 11), 2) + .wrapping_add((T[4] & (T[5] ^ T[6])).wrapping_add(T[5] & T[6])), + ); + W[5] = W[5].wrapping_add( + (rotr_32(W[3] ^ rotr_32(W[3], 2), 17) ^ W[3] >> 10) + .wrapping_add(W[14]) + .wrapping_add(rotr_32(W[6] ^ rotr_32(W[6], 11), 7) ^ W[6] >> 3), + ); + T[2] = T[2].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 14), 5), 6) + .wrapping_add(T[1] ^ T[7] & (T[0] ^ T[1])) + .wrapping_add(SHA256_K[5u32.wrapping_add(j) as usize]) + .wrapping_add(W[5]), + ); + T[6] = T[6].wrapping_add(T[2]); + T[2] = T[2].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 9), 11), 2) + .wrapping_add((T[3] & (T[4] ^ T[5])).wrapping_add(T[4] & T[5])), + ); + W[6] = W[6].wrapping_add( + (rotr_32(W[4] ^ rotr_32(W[4], 2), 17) ^ W[4] >> 10) + .wrapping_add(W[15]) + .wrapping_add(rotr_32(W[7] ^ rotr_32(W[7], 11), 7) ^ W[7] >> 3), + ); + T[1] = T[1].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 14), 5), 6) + .wrapping_add(T[0] ^ T[6] & (T[7] ^ T[0])) + .wrapping_add(SHA256_K[6u32.wrapping_add(j) as usize]) + .wrapping_add(W[6]), + ); + T[5] = T[5].wrapping_add(T[1]); + T[1] = T[1].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 9), 11), 2) + .wrapping_add((T[2] & (T[3] ^ T[4])).wrapping_add(T[3] & T[4])), + ); + W[7] = W[7].wrapping_add( + (rotr_32(W[5] ^ rotr_32(W[5], 2), 17) ^ W[5] >> 10) + .wrapping_add(W[0]) + .wrapping_add(rotr_32(W[8] ^ rotr_32(W[8], 11), 7) ^ W[8] >> 3), + ); + T[0] = T[0].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 14), 5), 6) + .wrapping_add(T[7] ^ T[5] & (T[6] ^ T[7])) + .wrapping_add(SHA256_K[7u32.wrapping_add(j) as usize]) + .wrapping_add(W[7]), + ); + T[4] = T[4].wrapping_add(T[0]); + T[0] = T[0].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 9), 11), 2) + .wrapping_add((T[1] & (T[2] ^ T[3])).wrapping_add(T[2] & T[3])), + ); + W[8] = W[8].wrapping_add( + (rotr_32(W[6] ^ rotr_32(W[6], 2), 17) ^ W[6] >> 10) + .wrapping_add(W[1]) + .wrapping_add(rotr_32(W[9] ^ rotr_32(W[9], 11), 7) ^ W[9] >> 3), + ); + T[7] = T[7].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 14), 5), 6) + .wrapping_add(T[6] ^ T[4] & (T[5] ^ T[6])) + .wrapping_add(SHA256_K[8u32.wrapping_add(j) as usize]) + .wrapping_add(W[8]), + ); + T[3] = T[3].wrapping_add(T[7]); + T[7] = T[7].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 9), 11), 2) + .wrapping_add((T[0] & (T[1] ^ T[2])).wrapping_add(T[1] & T[2])), + ); + W[9] = W[9].wrapping_add( + (rotr_32(W[7] ^ rotr_32(W[7], 2), 17) ^ W[7] >> 10) + .wrapping_add(W[2]) + .wrapping_add(rotr_32(W[10] ^ rotr_32(W[10], 11), 7) ^ W[10] >> 3), + ); + T[6] = T[6].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 14), 5), 6) + .wrapping_add(T[5] ^ T[3] & (T[4] ^ T[5])) + .wrapping_add(SHA256_K[9u32.wrapping_add(j) as usize]) + .wrapping_add(W[9]), + ); + T[2] = T[2].wrapping_add(T[6]); + T[6] = T[6].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 9), 11), 2) + .wrapping_add((T[7] & (T[0] ^ T[1])).wrapping_add(T[0] & T[1])), + ); + W[10] = W[10].wrapping_add( + (rotr_32(W[8] ^ rotr_32(W[8], 2), 17) ^ W[8] >> 10) + .wrapping_add(W[3]) + .wrapping_add(rotr_32(W[11] ^ rotr_32(W[11], 11), 7) ^ W[11] >> 3), + ); + T[5] = T[5].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 14), 5), 6) + .wrapping_add(T[4] ^ T[2] & (T[3] ^ T[4])) + .wrapping_add(SHA256_K[10u32.wrapping_add(j) as usize]) + .wrapping_add(W[10]), + ); + T[1] = T[1].wrapping_add(T[5]); + T[5] = T[5].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 9), 11), 2) + .wrapping_add((T[6] & (T[7] ^ T[0])).wrapping_add(T[7] & T[0])), + ); + W[11] = W[11].wrapping_add( + (rotr_32(W[9] ^ rotr_32(W[9], 2), 17) ^ W[9] >> 10) + .wrapping_add(W[4]) + .wrapping_add(rotr_32(W[12] ^ rotr_32(W[12], 11), 7) ^ W[12] >> 3), + ); + T[4] = T[4].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 14), 5), 6) + .wrapping_add(T[3] ^ T[1] & (T[2] ^ T[3])) + .wrapping_add(SHA256_K[11u32.wrapping_add(j) as usize]) + .wrapping_add(W[11]), + ); + T[0] = T[0].wrapping_add(T[4]); + T[4] = T[4].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 9), 11), 2) + .wrapping_add((T[5] & (T[6] ^ T[7])).wrapping_add(T[6] & T[7])), + ); + W[12] = W[12].wrapping_add( + (rotr_32(W[10] ^ rotr_32(W[10], 2), 17) ^ W[10] >> 10) + .wrapping_add(W[5]) + .wrapping_add(rotr_32(W[13] ^ rotr_32(W[13], 11), 7) ^ W[13] >> 3), + ); + T[3] = T[3].wrapping_add( + rotr_32(T[0] ^ rotr_32(T[0] ^ rotr_32(T[0], 14), 5), 6) + .wrapping_add(T[2] ^ T[0] & (T[1] ^ T[2])) + .wrapping_add(SHA256_K[12u32.wrapping_add(j) as usize]) + .wrapping_add(W[12]), + ); + T[7] = T[7].wrapping_add(T[3]); + T[3] = T[3].wrapping_add( + rotr_32(T[4] ^ rotr_32(T[4] ^ rotr_32(T[4], 9), 11), 2) + .wrapping_add((T[4] & (T[5] ^ T[6])).wrapping_add(T[5] & T[6])), + ); + W[13] = W[13].wrapping_add( + (rotr_32(W[11] ^ rotr_32(W[11], 2), 17) ^ W[11] >> 10) + .wrapping_add(W[6]) + .wrapping_add(rotr_32(W[14] ^ rotr_32(W[14], 11), 7) ^ W[14] >> 3), + ); + T[2] = T[2].wrapping_add( + rotr_32(T[7] ^ rotr_32(T[7] ^ rotr_32(T[7], 14), 5), 6) + .wrapping_add(T[1] ^ T[7] & (T[0] ^ T[1])) + .wrapping_add(SHA256_K[13u32.wrapping_add(j) as usize]) + .wrapping_add(W[13]), + ); + T[6] = T[6].wrapping_add(T[2]); + T[2] = T[2].wrapping_add( + rotr_32(T[3] ^ rotr_32(T[3] ^ rotr_32(T[3], 9), 11), 2) + .wrapping_add((T[3] & (T[4] ^ T[5])).wrapping_add(T[4] & T[5])), + ); + W[14] = W[14].wrapping_add( + (rotr_32(W[12] ^ rotr_32(W[12], 2), 17) ^ W[12] >> 10) + .wrapping_add(W[7]) + .wrapping_add(rotr_32(W[15] ^ rotr_32(W[15], 11), 7) ^ W[15] >> 3), + ); + T[1] = T[1].wrapping_add( + rotr_32(T[6] ^ rotr_32(T[6] ^ rotr_32(T[6], 14), 5), 6) + .wrapping_add(T[0] ^ T[6] & (T[7] ^ T[0])) + .wrapping_add(SHA256_K[14u32.wrapping_add(j) as usize]) + .wrapping_add(W[14]), + ); + T[5] = T[5].wrapping_add(T[1]); + T[1] = T[1].wrapping_add( + rotr_32(T[2] ^ rotr_32(T[2] ^ rotr_32(T[2], 9), 11), 2) + .wrapping_add((T[2] & (T[3] ^ T[4])).wrapping_add(T[3] & T[4])), + ); + W[15] = W[15].wrapping_add( + (rotr_32(W[13] ^ rotr_32(W[13], 2), 17) ^ W[13] >> 10) + .wrapping_add(W[8]) + .wrapping_add(rotr_32(W[0] ^ rotr_32(W[0], 11), 7) ^ W[0] >> 3), + ); + T[0] = T[0].wrapping_add( + rotr_32(T[5] ^ rotr_32(T[5] ^ rotr_32(T[5], 14), 5), 6) + .wrapping_add(T[7] ^ T[5] & (T[6] ^ T[7])) + .wrapping_add(SHA256_K[15u32.wrapping_add(j) as usize]) + .wrapping_add(W[15]), + ); + T[4] = T[4].wrapping_add(T[0]); + T[0] = T[0].wrapping_add( + rotr_32(T[1] ^ rotr_32(T[1] ^ rotr_32(T[1], 9), 11), 2) + .wrapping_add((T[1] & (T[2] ^ T[3])).wrapping_add(T[2] & T[3])), + ); + j = j.wrapping_add(16); + } + for i in 0..8 { + *state.offset(i as isize) = (*state.offset(i as isize)).wrapping_add(T[i]); + } +} +unsafe fn process(check: *mut lzma_check_state) { + transform( + ::core::ptr::addr_of_mut!((*check).state.sha256.state) as *mut u32, + ::core::ptr::addr_of_mut!((*check).buffer.u32_0) as *const u32, + ); +} +pub unsafe fn lzma_sha256_init(check: *mut lzma_check_state) { + static mut s: [u32; 8] = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, + 0x5be0cd19, + ]; + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of!(s) as *const u8, + ::core::ptr::addr_of_mut!((*check).state.sha256.state) as *mut u8, + core::mem::size_of::<[u32; 8]>(), + ); + (*check).state.sha256.size = 0; +} +pub unsafe fn lzma_sha256_update( + mut buf: *const u8, + mut size: size_t, + check: *mut lzma_check_state, +) { + while size > 0 { + let copy_start: size_t = ((*check).state.sha256.size & 0x3f as u64) as size_t; + let mut copy_size: size_t = (64_usize).wrapping_sub(copy_start); + if copy_size > size { + copy_size = size; + } + core::ptr::copy_nonoverlapping( + buf as *const u8, + (::core::ptr::addr_of_mut!((*check).buffer.u8_0) as *mut u8).offset(copy_start as isize) + as *mut u8, + copy_size, + ); + buf = buf.offset(copy_size as isize); + size = size.wrapping_sub(copy_size); + (*check).state.sha256.size = (*check).state.sha256.size.wrapping_add(copy_size as u64); + if (*check).state.sha256.size & 0x3f as u64 == 0 { + process(check); + } + } +} +pub unsafe fn lzma_sha256_finish(check: *mut lzma_check_state) { + let mut pos: size_t = ((*check).state.sha256.size & 0x3f as u64) as size_t; + (*check).buffer.u8_0[pos as usize] = 0x80 as u8; + pos += 1; + while pos != (64 - 8) as size_t { + if pos == 64 { + process(check); + pos = 0; + } + (*check).buffer.u8_0[pos as usize] = 0; + pos += 1; + } + (*check).state.sha256.size = (*check).state.sha256.size.wrapping_mul(8); + (*check).buffer.u64_0[7] = ((*check).state.sha256.size & 0xff as u64) << 56 + | ((*check).state.sha256.size & 0xff00 as u64) << 40 + | ((*check).state.sha256.size & 0xff0000 as u64) << 24 + | ((*check).state.sha256.size & 0xff000000 as u64) << 8 + | ((*check).state.sha256.size & 0xff00000000 as u64) >> 8 + | ((*check).state.sha256.size & 0xff0000000000 as u64) >> 24 + | ((*check).state.sha256.size & 0xff000000000000 as u64) >> 40 + | ((*check).state.sha256.size & 0xff00000000000000 as u64) >> 56; + process(check); + let mut i: size_t = 0; + while i < 8 { + (*check).buffer.u32_0[i as usize] = ((*check).state.sha256.state[i as usize] & 0xff) << 24 + | ((*check).state.sha256.state[i as usize] & 0xff00) << 8 + | ((*check).state.sha256.state[i as usize] & 0xff0000) >> 8 + | ((*check).state.sha256.state[i as usize] & 0xff000000) >> 24; + i += 1; + } +} diff --git a/liblzma-rs/src/common/alone_decoder.rs b/liblzma-rs/src/common/alone_decoder.rs new file mode 100644 index 00000000..31de9d99 --- /dev/null +++ b/liblzma-rs/src/common/alone_decoder.rs @@ -0,0 +1,293 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_alone_coder { + pub next: lzma_next_coder, + pub sequence: alone_decoder_seq, + pub picky: bool, + pub pos: size_t, + pub uncompressed_size: lzma_vli, + pub memlimit: u64, + pub memusage: u64, + pub options: lzma_options_lzma, +} +pub type alone_decoder_seq = c_uint; +pub const SEQ_CODE: alone_decoder_seq = 4; +pub const SEQ_CODER_INIT: alone_decoder_seq = 3; +pub const SEQ_UNCOMPRESSED_SIZE: alone_decoder_seq = 2; +pub const SEQ_DICTIONARY_SIZE: alone_decoder_seq = 1; +pub const SEQ_PROPERTIES: alone_decoder_seq = 0; +unsafe extern "C" fn alone_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_alone_coder = coder_ptr as *mut lzma_alone_coder; + while *out_pos < out_size && ((*coder).sequence == SEQ_CODE || *in_pos < in_size) { + let current_block_42: u64; + match (*coder).sequence { + 0 => { + if lzma_lzma_lclppb_decode( + ::core::ptr::addr_of_mut!((*coder).options), + *in_0.offset(*in_pos as isize), + ) { + return LZMA_FORMAT_ERROR; + } + (*coder).sequence = SEQ_DICTIONARY_SIZE; + *in_pos += 1; + current_block_42 = 11048769245176032998; + } + 1 => { + (*coder).options.dict_size = ((*coder).options.dict_size as size_t + | (*in_0.offset(*in_pos as isize) as size_t) << ((*coder).pos * 8)) + as u32; + (*coder).pos += 1; + if (*coder).pos == 4 { + if (*coder).picky && (*coder).options.dict_size != UINT32_MAX { + let mut d: u32 = (*coder).options.dict_size.wrapping_sub(1); + d |= d >> 2; + d |= d >> 3; + d |= d >> 4; + d |= d >> 8; + d |= d >> 16; + d += 1; + if d != (*coder).options.dict_size { + return LZMA_FORMAT_ERROR; + } + } + (*coder).pos = 0; + (*coder).sequence = SEQ_UNCOMPRESSED_SIZE; + } + *in_pos += 1; + current_block_42 = 11048769245176032998; + } + 2 => { + (*coder).uncompressed_size |= + (*in_0.offset(*in_pos as isize) as lzma_vli) << ((*coder).pos * 8); + *in_pos += 1; + (*coder).pos += 1; + if (*coder).pos < 8 { + current_block_42 = 11048769245176032998; + } else { + if (*coder).picky + && (*coder).uncompressed_size != LZMA_VLI_UNKNOWN + && (*coder).uncompressed_size >= 1 << 38 + { + return LZMA_FORMAT_ERROR; + } + (*coder).options.ext_flags = LZMA_LZMA1EXT_ALLOW_EOPM as u32; + (*coder).options.ext_size_low = (*coder).uncompressed_size as u32; + (*coder).options.ext_size_high = ((*coder).uncompressed_size >> 32) as u32; + (*coder).memusage = lzma_lzma_decoder_memusage_nocheck( + ::core::ptr::addr_of_mut!((*coder).options) as *const c_void, + ) + .wrapping_add(LZMA_MEMUSAGE_BASE); + (*coder).pos = 0; + (*coder).sequence = SEQ_CODER_INIT; + current_block_42 = 14763689060501151050; + } + } + 3 => { + current_block_42 = 14763689060501151050; + } + 4 => { + return (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + } + _ => return LZMA_PROG_ERROR, + } + match current_block_42 { + 14763689060501151050 => { + if (*coder).memusage > (*coder).memlimit { + return LZMA_MEMLIMIT_ERROR; + } + let mut filters: [lzma_filter_info; 2] = [ + lzma_filter_info_s { + id: LZMA_FILTER_LZMA1EXT, + init: Some( + lzma_lzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) + -> lzma_ret, + ), + options: ::core::ptr::addr_of_mut!((*coder).options) as *mut c_void, + }, + lzma_filter_info_s { + id: 0, + init: None, + options: core::ptr::null_mut(), + }, + ]; + let ret_: lzma_ret = lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter_info, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).sequence = SEQ_CODE; + } + _ => {} + } + } + LZMA_OK +} +unsafe extern "C" fn alone_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_alone_coder = coder_ptr as *mut lzma_alone_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn alone_decoder_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_alone_coder = coder_ptr as *mut lzma_alone_coder; + *memusage = (*coder).memusage; + *old_memlimit = (*coder).memlimit; + if new_memlimit != 0 { + if new_memlimit < (*coder).memusage { + return LZMA_MEMLIMIT_ERROR; + } + (*coder).memlimit = new_memlimit; + } + LZMA_OK +} +pub unsafe extern "C" fn lzma_alone_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + memlimit: u64, + picky: bool, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + bool, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_alone_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + bool, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + bool, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_alone_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + bool, + ) -> lzma_ret, + )); + let mut coder: *mut lzma_alone_coder = (*next).coder as *mut lzma_alone_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + alone_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + alone_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).memconfig = Some( + alone_decoder_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + (*coder).sequence = SEQ_PROPERTIES; + (*coder).picky = picky; + (*coder).pos = 0; + (*coder).options.dict_size = 0; + (*coder).options.preset_dict = core::ptr::null(); + (*coder).options.preset_dict_size = 0; + (*coder).uncompressed_size = 0; + (*coder).memlimit = if 1 > memlimit { 1 } else { memlimit }; + (*coder).memusage = LZMA_MEMUSAGE_BASE; + LZMA_OK +} +pub unsafe fn lzma_alone_decoder(strm: *mut lzma_stream, memlimit: u64) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_alone_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + memlimit, + false, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/alone_encoder.rs b/liblzma-rs/src/common/alone_encoder.rs new file mode 100644 index 00000000..921236a8 --- /dev/null +++ b/liblzma-rs/src/common/alone_encoder.rs @@ -0,0 +1,220 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_alone_coder { + pub next: lzma_next_coder, + pub sequence: alone_encoder_seq, + pub header_pos: size_t, + pub header: [u8; 13], +} +pub type alone_encoder_seq = c_uint; +pub const SEQ_CODE: alone_encoder_seq = 1; +pub const SEQ_HEADER: alone_encoder_seq = 0; +pub const ALONE_HEADER_SIZE: u32 = 1 + 4 + 8; +unsafe extern "C" fn alone_encode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_alone_coder = coder_ptr as *mut lzma_alone_coder; + while *out_pos < out_size { + match (*coder).sequence { + 0 => { + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).header) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).header_pos), + ALONE_HEADER_SIZE as size_t, + out, + out_pos, + out_size, + ); + if (*coder).header_pos < ALONE_HEADER_SIZE as size_t { + return LZMA_OK; + } + (*coder).sequence = SEQ_CODE; + } + 1 => { + return (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + } + _ => return LZMA_PROG_ERROR, + } + } + LZMA_OK +} +unsafe extern "C" fn alone_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_alone_coder = coder_ptr as *mut lzma_alone_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn alone_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + options: *const lzma_options_lzma, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + alone_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + alone_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + )); + let mut coder: *mut lzma_alone_coder = (*next).coder as *mut lzma_alone_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + alone_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + alone_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + (*coder).sequence = SEQ_HEADER; + (*coder).header_pos = 0; + if lzma_lzma_lclppb_encode( + options, + ::core::ptr::addr_of_mut!((*coder).header) as *mut u8, + ) { + return LZMA_OPTIONS_ERROR; + } + if (*options).dict_size < LZMA_DICT_SIZE_MIN as u32 { + return LZMA_OPTIONS_ERROR; + } + let mut d: u32 = (*options).dict_size - 1; + d |= d >> 2; + d |= d >> 3; + d |= d >> 4; + d |= d >> 8; + d |= d >> 16; + if d != UINT32_MAX { + d += 1; + } + write32le( + (::core::ptr::addr_of_mut!((*coder).header) as *mut u8).offset(1), + d, + ); + core::ptr::write_bytes( + (::core::ptr::addr_of_mut!((*coder).header) as *mut u8) + .offset(1) + .offset(4) as *mut u8, + 0xff as u8, + 8, + ); + let filters: [lzma_filter_info; 2] = [ + lzma_filter_info_s { + id: LZMA_FILTER_LZMA1, + init: Some( + lzma_lzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + options: options as *mut c_void, + }, + lzma_filter_info_s { + id: 0, + init: None, + options: core::ptr::null_mut(), + }, + ]; + lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + ::core::ptr::addr_of!(filters) as *const lzma_filter_info, + ) +} +pub unsafe fn lzma_alone_encoder( + strm: *mut lzma_stream, + options: *const lzma_options_lzma, +) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = alone_encoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + options, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/auto_decoder.rs b/liblzma-rs/src/common/auto_decoder.rs new file mode 100644 index 00000000..a46b44f0 --- /dev/null +++ b/liblzma-rs/src/common/auto_decoder.rs @@ -0,0 +1,254 @@ +use crate::common::alone_decoder::lzma_alone_decoder_init; +use crate::types::*; +pub type auto_decoder_seq = c_uint; +pub const SEQ_FINISH: auto_decoder_seq = 2; +pub const SEQ_CODE: auto_decoder_seq = 1; +pub const SEQ_INIT: auto_decoder_seq = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_auto_coder { + pub next: lzma_next_coder, + pub memlimit: u64, + pub flags: u32, + pub sequence: auto_decoder_seq, +} +unsafe extern "C" fn auto_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_auto_coder = coder_ptr as *mut lzma_auto_coder; + let current_block_28: u64; + match (*coder).sequence { + 0 => { + if *in_pos >= in_size { + return LZMA_OK; + } + (*coder).sequence = SEQ_CODE; + if *in_0.offset(*in_pos as isize) == 0xfd { + let ret_: lzma_ret = lzma_stream_decoder_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + (*coder).memlimit, + (*coder).flags, + ); + if ret_ != LZMA_OK { + return ret_; + } + } else { + let ret__0: lzma_ret = lzma_alone_decoder_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + (*coder).memlimit, + true, + ); + if ret__0 != LZMA_OK { + return ret__0; + } + if (*coder).flags & LZMA_TELL_NO_CHECK as u32 != 0 { + return LZMA_NO_CHECK; + } + if (*coder).flags & LZMA_TELL_ANY_CHECK as u32 != 0 { + return LZMA_GET_CHECK; + } + } + current_block_28 = 13935781298497728377; + } + 1 => { + current_block_28 = 13935781298497728377; + } + 2 => { + current_block_28 = 4647193646042868866; + } + _ => return LZMA_PROG_ERROR, + } + match current_block_28 { + 13935781298497728377 => { + let code = if let Some(code) = (*coder).next.code { + code + } else { + return LZMA_PROG_ERROR; + }; + let ret: lzma_ret = code( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + if ret != LZMA_STREAM_END || (*coder).flags & LZMA_CONCATENATED as u32 == 0 { + return ret; + } + (*coder).sequence = SEQ_FINISH; + } + _ => {} + } + if *in_pos < in_size { + return LZMA_DATA_ERROR; + } + if action == LZMA_FINISH { + LZMA_STREAM_END + } else { + LZMA_OK + } +} +unsafe extern "C" fn auto_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_auto_coder = coder_ptr as *mut lzma_auto_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +extern "C" fn auto_decoder_get_check(coder_ptr: *const c_void) -> lzma_check { + return unsafe { + let coder: *const lzma_auto_coder = coder_ptr as *const lzma_auto_coder; + (if (*coder).next.get_check.is_none() { + LZMA_CHECK_NONE + } else { + (*coder).next.get_check.unwrap()((*coder).next.coder) + }) as lzma_check + }; +} +unsafe extern "C" fn auto_decoder_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_auto_coder = coder_ptr as *mut lzma_auto_coder; + let mut ret: lzma_ret = LZMA_OK; + if (*coder).next.memconfig.is_some() { + ret = (*coder).next.memconfig.unwrap()( + (*coder).next.coder, + memusage, + old_memlimit, + new_memlimit, + ); + } else { + *memusage = LZMA_MEMUSAGE_BASE; + *old_memlimit = (*coder).memlimit; + ret = LZMA_OK; + if new_memlimit != 0 && new_memlimit < *memusage { + ret = LZMA_MEMLIMIT_ERROR; + } + } + if ret == LZMA_OK && new_memlimit != 0 { + (*coder).memlimit = new_memlimit; + } + ret +} +unsafe extern "C" fn auto_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + memlimit: u64, + flags: u32, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn(*mut lzma_next_coder, *const lzma_allocator, u64, u32) -> lzma_ret, + >, + uintptr_t, + >(Some( + auto_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u32, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn(*mut lzma_next_coder, *const lzma_allocator, u64, u32) -> lzma_ret, + >, + uintptr_t, + >(Some( + auto_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u32, + ) -> lzma_ret, + )); + if flags & !(LZMA_SUPPORTED_FLAGS as u32) != 0 { + return LZMA_OPTIONS_ERROR; + } + let mut coder: *mut lzma_auto_coder = (*next).coder as *mut lzma_auto_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + auto_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + auto_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).get_check = + Some(auto_decoder_get_check as unsafe extern "C" fn(*const c_void) -> lzma_check); + (*next).memconfig = Some( + auto_decoder_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + (*coder).memlimit = if 1 > memlimit { 1 } else { memlimit }; + (*coder).flags = flags; + (*coder).sequence = SEQ_INIT; + LZMA_OK +} +pub unsafe fn lzma_auto_decoder(strm: *mut lzma_stream, memlimit: u64, flags: u32) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = auto_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + memlimit, + flags, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/block_buffer_decoder.rs b/liblzma-rs/src/common/block_buffer_decoder.rs new file mode 100644 index 00000000..e992d72c --- /dev/null +++ b/liblzma-rs/src/common/block_buffer_decoder.rs @@ -0,0 +1,71 @@ +use crate::types::*; +pub unsafe fn lzma_block_buffer_decode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if in_pos.is_null() + || in_0.is_null() && *in_pos != in_size + || *in_pos > in_size + || out_pos.is_null() + || out.is_null() && *out_pos != out_size + || *out_pos > out_size + { + return LZMA_PROG_ERROR; + } + let mut block_decoder: lzma_next_coder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + let mut ret: lzma_ret = + lzma_block_decoder_init(::core::ptr::addr_of_mut!(block_decoder), allocator, block); + if ret == LZMA_OK { + let code = if let Some(code) = block_decoder.code { + code + } else { + lzma_next_end(::core::ptr::addr_of_mut!(block_decoder), allocator); + return LZMA_PROG_ERROR; + }; + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + ret = code( + block_decoder.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + LZMA_FINISH, + ); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + } else { + if ret == LZMA_OK { + if *in_pos == in_size { + ret = LZMA_DATA_ERROR; + } else { + ret = LZMA_BUF_ERROR; + } + } + *in_pos = in_start; + *out_pos = out_start; + } + } + lzma_next_end(::core::ptr::addr_of_mut!(block_decoder), allocator); + ret +} diff --git a/liblzma-rs/src/common/block_buffer_encoder.rs b/liblzma-rs/src/common/block_buffer_encoder.rs new file mode 100644 index 00000000..1c9a8381 --- /dev/null +++ b/liblzma-rs/src/common/block_buffer_encoder.rs @@ -0,0 +1,301 @@ +use crate::types::*; +pub const HEADERS_BOUND: u32 = + 1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 3 + 4 + LZMA_CHECK_SIZE_MAX + 3 & !(3); +extern "C" fn lzma2_bound(uncompressed_size: u64) -> u64 { + if uncompressed_size > COMPRESSED_SIZE_MAX as u64 { + return 0; + } + let overhead: u64 = uncompressed_size + .wrapping_add(LZMA2_CHUNK_MAX as u64) + .wrapping_sub(1) + .wrapping_div(LZMA2_CHUNK_MAX as u64) + .wrapping_mul(LZMA2_HEADER_UNCOMPRESSED as u64) + .wrapping_add(1); + if (COMPRESSED_SIZE_MAX as u64).wrapping_sub(overhead) < uncompressed_size { + return 0; + } + uncompressed_size + overhead +} +pub fn lzma_block_buffer_bound64(uncompressed_size: u64) -> u64 { + let mut lzma2_size: u64 = lzma2_bound(uncompressed_size); + if lzma2_size == 0 { + return 0; + } + lzma2_size = (lzma2_size + 3) & !(3); + HEADERS_BOUND as u64 + lzma2_size +} +pub fn lzma_block_buffer_bound(uncompressed_size: size_t) -> size_t { + let ret: u64 = lzma_block_buffer_bound64(uncompressed_size as u64); + ret as size_t +} +unsafe fn block_encode_uncompressed( + block: *mut lzma_block, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + let mut lzma2: lzma_options_lzma = lzma_options_lzma { + dict_size: LZMA_DICT_SIZE_MIN as u32, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }; + let mut filters: [lzma_filter; 2] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 2]; + filters[0].id = LZMA_FILTER_LZMA2; + filters[0].options = ::core::ptr::addr_of_mut!(lzma2) as *mut c_void; + filters[1].id = LZMA_VLI_UNKNOWN; + let filters_orig: *mut lzma_filter = (*block).filters; + (*block).filters = ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter; + if lzma_block_header_size(block) != LZMA_OK { + (*block).filters = filters_orig; + return LZMA_PROG_ERROR; + } + if ((out_size - *out_pos) as lzma_vli) + < (*block).header_size as lzma_vli + (*block).compressed_size + { + (*block).filters = filters_orig; + return LZMA_BUF_ERROR; + } + if lzma_block_header_encode(block, out.offset(*out_pos as isize)) != LZMA_OK { + (*block).filters = filters_orig; + return LZMA_PROG_ERROR; + } + (*block).filters = filters_orig; + *out_pos += (*block).header_size as size_t; + let mut in_pos: size_t = 0; + let mut control: u8 = 0x1 as u8; + while in_pos < in_size { + *out.offset(*out_pos as isize) = control; + *out_pos += 1; + control = 0x2 as u8; + let copy_size: size_t = if in_size - in_pos < (1u32 << 16) as size_t { + in_size - in_pos + } else { + (1u32 << 16) as size_t + }; + *out.offset(*out_pos as isize) = ((copy_size - 1) >> 8) as u8; + *out_pos += 1; + *out.offset(*out_pos as isize) = ((copy_size - 1) & 0xff) as u8; + *out_pos += 1; + core::ptr::copy_nonoverlapping( + in_0.offset(in_pos as isize) as *const u8, + out.offset(*out_pos as isize) as *mut u8, + copy_size, + ); + in_pos += copy_size; + *out_pos += copy_size; + } + *out.offset(*out_pos as isize) = 0; + *out_pos += 1; + LZMA_OK +} +unsafe fn block_encode_normal( + block: *mut lzma_block, + allocator: *const lzma_allocator, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + mut out_size: size_t, +) -> lzma_ret { + let ret_: lzma_ret = lzma_block_header_size(block); + if ret_ != LZMA_OK { + return ret_; + } + if out_size - *out_pos <= (*block).header_size as size_t { + return LZMA_BUF_ERROR; + } + let out_start: size_t = *out_pos; + *out_pos += (*block).header_size as size_t; + if (out_size - *out_pos) as lzma_vli > (*block).compressed_size { + out_size = (*out_pos as lzma_vli + (*block).compressed_size) as size_t; + } + let mut raw_encoder: lzma_next_coder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + let mut ret: lzma_ret = lzma_raw_encoder_init( + ::core::ptr::addr_of_mut!(raw_encoder), + allocator, + (*block).filters, + ); + if ret == LZMA_OK { + let mut in_pos: size_t = 0; + ret = raw_encoder.code.unwrap()( + raw_encoder.coder, + allocator, + in_0, + ::core::ptr::addr_of_mut!(in_pos), + in_size, + out, + out_pos, + out_size, + LZMA_FINISH, + ); + } + lzma_next_end(::core::ptr::addr_of_mut!(raw_encoder), allocator); + if ret == LZMA_STREAM_END { + (*block).compressed_size = + (*out_pos - (out_start + (*block).header_size as size_t)) as lzma_vli; + ret = lzma_block_header_encode(block, out.offset(out_start as isize)); + if ret != LZMA_OK { + ret = LZMA_PROG_ERROR; + } + } else if ret == LZMA_OK { + ret = LZMA_BUF_ERROR; + } + if ret != LZMA_OK { + *out_pos = out_start; + } + ret +} +unsafe fn block_buffer_encode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + mut out_size: size_t, + try_to_compress: bool, +) -> lzma_ret { + if block.is_null() + || in_0.is_null() && in_size != 0 + || out.is_null() + || out_pos.is_null() + || *out_pos > out_size + { + return LZMA_PROG_ERROR; + } + if (*block).version > 1 { + return LZMA_OPTIONS_ERROR; + } + if (*block).check > LZMA_CHECK_ID_MAX || try_to_compress && (*block).filters.is_null() { + return LZMA_PROG_ERROR; + } + if lzma_check_is_supported((*block).check) == 0 { + return LZMA_UNSUPPORTED_CHECK; + } + out_size -= (out_size - *out_pos) & 3; + let check_size: size_t = lzma_check_size((*block).check) as size_t; + if out_size - *out_pos <= check_size { + return LZMA_BUF_ERROR; + } + out_size -= check_size; + (*block).uncompressed_size = in_size as lzma_vli; + (*block).compressed_size = lzma2_bound(in_size as u64) as lzma_vli; + if (*block).compressed_size == 0 { + return LZMA_DATA_ERROR; + } + let mut ret: lzma_ret = LZMA_BUF_ERROR; + if try_to_compress { + ret = block_encode_normal(block, allocator, in_0, in_size, out, out_pos, out_size); + } + if ret != LZMA_OK { + if ret != LZMA_BUF_ERROR { + return ret; + } + let ret_: lzma_ret = + block_encode_uncompressed(block, in_0, in_size, out, out_pos, out_size); + if ret_ != LZMA_OK { + return ret_; + } + } + let mut i: size_t = (*block).compressed_size as size_t; + while i & 3 != 0 { + *out.offset(*out_pos as isize) = 0; + *out_pos += 1; + i += 1; + } + if check_size > 0 { + let mut check: lzma_check_state = lzma_check_state { + buffer: lzma_check_state_buffer { u8_0: [0; 64] }, + state: lzma_check_state_inner { crc32: 0 }, + }; + lzma_check_init(::core::ptr::addr_of_mut!(check), (*block).check); + lzma_check_update( + ::core::ptr::addr_of_mut!(check), + (*block).check, + in_0, + in_size, + ); + lzma_check_finish(::core::ptr::addr_of_mut!(check), (*block).check); + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!(check.buffer.u8_0) as *const u8, + ::core::ptr::addr_of_mut!((*block).raw_check) as *mut u8, + check_size, + ); + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!(check.buffer.u8_0) as *const u8, + out.offset(*out_pos as isize) as *mut u8, + check_size, + ); + *out_pos += check_size; + } + LZMA_OK +} +pub unsafe fn lzma_block_buffer_encode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + block_buffer_encode( + block, allocator, in_0, in_size, out, out_pos, out_size, true, + ) +} +pub unsafe fn lzma_block_uncomp_encode( + block: *mut lzma_block, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + block_buffer_encode( + block, + core::ptr::null(), + in_0, + in_size, + out, + out_pos, + out_size, + false, + ) +} diff --git a/liblzma-rs/src/common/block_decoder.rs b/liblzma-rs/src/common/block_decoder.rs new file mode 100644 index 00000000..90ea969e --- /dev/null +++ b/liblzma-rs/src/common/block_decoder.rs @@ -0,0 +1,296 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_block_coder { + pub sequence: block_decoder_seq, + pub next: lzma_next_coder, + pub block: *mut lzma_block, + pub compressed_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub compressed_limit: lzma_vli, + pub uncompressed_limit: lzma_vli, + pub check_pos: size_t, + pub check: lzma_check_state, + pub ignore_check: bool, +} +pub type block_decoder_seq = c_uint; +pub const SEQ_CHECK: block_decoder_seq = 2; +pub const SEQ_PADDING: block_decoder_seq = 1; +pub const SEQ_CODE: block_decoder_seq = 0; +#[inline] +extern "C" fn is_size_valid(size: lzma_vli, reference: lzma_vli) -> bool { + reference == LZMA_VLI_UNKNOWN || reference == size +} +unsafe extern "C" fn block_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_block_coder = coder_ptr as *mut lzma_block_coder; + let current_block_40: u64 = match (*coder).sequence { + 0 => { + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + let in_stop: size_t = *in_pos + + (if ((in_size - *in_pos) as lzma_vli) + < (*coder).compressed_limit - (*coder).compressed_size + { + (in_size - *in_pos) as lzma_vli + } else { + (*coder).compressed_limit - (*coder).compressed_size + }) as size_t; + let out_stop: size_t = *out_pos + + (if ((out_size - *out_pos) as lzma_vli) + < (*coder).uncompressed_limit - (*coder).uncompressed_size + { + (out_size - *out_pos) as lzma_vli + } else { + (*coder).uncompressed_limit - (*coder).uncompressed_size + }) as size_t; + let ret: lzma_ret = (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_stop, + out, + out_pos, + out_stop, + action, + ); + let in_used: size_t = *in_pos - in_start; + let out_used: size_t = *out_pos - out_start; + (*coder).compressed_size += in_used as lzma_vli; + (*coder).uncompressed_size += out_used as lzma_vli; + if ret == LZMA_OK { + let comp_done: bool = (*coder).compressed_size == (*(*coder).block).compressed_size; + let uncomp_done: bool = + (*coder).uncompressed_size == (*(*coder).block).uncompressed_size; + if comp_done && uncomp_done { + return LZMA_DATA_ERROR; + } + if comp_done && *out_pos < out_size { + return LZMA_DATA_ERROR; + } + if uncomp_done && *in_pos < in_size { + return LZMA_DATA_ERROR; + } + } + if !(*coder).ignore_check && out_used > 0 { + lzma_check_update( + ::core::ptr::addr_of_mut!((*coder).check), + (*(*coder).block).check, + out.offset(out_start as isize), + out_used, + ); + } + if ret != LZMA_STREAM_END { + return ret; + } + if !is_size_valid((*coder).compressed_size, (*(*coder).block).compressed_size) + || !is_size_valid( + (*coder).uncompressed_size, + (*(*coder).block).uncompressed_size, + ) + { + return LZMA_DATA_ERROR; + } + (*(*coder).block).compressed_size = (*coder).compressed_size; + (*(*coder).block).uncompressed_size = (*coder).uncompressed_size; + (*coder).sequence = SEQ_PADDING; + 17473121293339793080 + } + 1 => 17473121293339793080, + 2 => 9393557385011460022, + _ => return LZMA_PROG_ERROR, + }; + if current_block_40 == 17473121293339793080 { + while (*coder).compressed_size & 3 != 0 { + if *in_pos >= in_size { + return LZMA_OK; + } + (*coder).compressed_size += 1; + let byte = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if byte != 0 { + return LZMA_DATA_ERROR; + } + } + if (*(*coder).block).check == LZMA_CHECK_NONE { + return LZMA_STREAM_END; + } + if !(*coder).ignore_check { + lzma_check_finish( + ::core::ptr::addr_of_mut!((*coder).check), + (*(*coder).block).check, + ); + } + (*coder).sequence = SEQ_CHECK; + } + let check_size: size_t = lzma_check_size((*(*coder).block).check) as size_t; + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*(*coder).block).raw_check) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).check_pos), + check_size, + ); + if (*coder).check_pos < check_size { + return LZMA_OK; + } + if !(*coder).ignore_check + && lzma_check_is_supported((*(*coder).block).check) != 0 + && memcmp( + ::core::ptr::addr_of_mut!((*(*coder).block).raw_check) as *const c_void, + ::core::ptr::addr_of_mut!((*coder).check.buffer.u8_0) as *const c_void, + check_size, + ) != 0 + { + return LZMA_DATA_ERROR; + } + LZMA_STREAM_END +} +unsafe extern "C" fn block_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_block_coder = coder_ptr as *mut lzma_block_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +pub unsafe extern "C" fn lzma_block_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + block: *mut lzma_block, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_block_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_block_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + )); + if lzma_block_unpadded_size(block) == 0 + || !((*block).uncompressed_size <= LZMA_VLI_MAX + || (*block).uncompressed_size == LZMA_VLI_UNKNOWN) + { + return LZMA_PROG_ERROR; + } + let mut coder: *mut lzma_block_coder = (*next).coder as *mut lzma_block_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + block_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + block_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + (*coder).sequence = SEQ_CODE; + (*coder).block = block; + (*coder).compressed_size = 0; + (*coder).uncompressed_size = 0; + (*coder).compressed_limit = if (*block).compressed_size == LZMA_VLI_UNKNOWN { + (LZMA_VLI_MAX & !(3)) + - (*block).header_size as lzma_vli + - lzma_check_size((*block).check) as lzma_vli + } else { + (*block).compressed_size + }; + (*coder).uncompressed_limit = if (*block).uncompressed_size == LZMA_VLI_UNKNOWN { + LZMA_VLI_MAX + } else { + (*block).uncompressed_size + }; + (*coder).check_pos = 0; + lzma_check_init(::core::ptr::addr_of_mut!((*coder).check), (*block).check); + (*coder).ignore_check = if (*block).version >= 1 { + (*block).ignore_check != 0 + } else { + false + }; + lzma_raw_decoder_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + (*block).filters, + ) +} +pub unsafe fn lzma_block_decoder(strm: *mut lzma_stream, block: *mut lzma_block) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_block_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + block, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/block_encoder.rs b/liblzma-rs/src/common/block_encoder.rs new file mode 100644 index 00000000..25c6ac1f --- /dev/null +++ b/liblzma-rs/src/common/block_encoder.rs @@ -0,0 +1,264 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_block_coder { + pub next: lzma_next_coder, + pub block: *mut lzma_block, + pub sequence: block_encoder_seq, + pub compressed_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub pos: size_t, + pub check: lzma_check_state, +} +pub type block_encoder_seq = c_uint; +pub const SEQ_CHECK: block_encoder_seq = 2; +pub const SEQ_PADDING: block_encoder_seq = 1; +pub const SEQ_CODE: block_encoder_seq = 0; +unsafe extern "C" fn block_encode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_block_coder = coder_ptr as *mut lzma_block_coder; + if (LZMA_VLI_MAX).wrapping_sub((*coder).uncompressed_size) + < in_size.wrapping_sub(*in_pos) as lzma_vli + { + return LZMA_DATA_ERROR; + } + let current_block_34: u64 = match (*coder).sequence { + 0 => { + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + let ret: lzma_ret = (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + let in_used: size_t = *in_pos - in_start; + let out_used: size_t = *out_pos - out_start; + if (COMPRESSED_SIZE_MAX).wrapping_sub((*coder).compressed_size) < out_used as lzma_vli { + return LZMA_DATA_ERROR; + } + (*coder).compressed_size += out_used as lzma_vli; + (*coder).uncompressed_size += in_used as lzma_vli; + if in_used > 0 { + lzma_check_update( + ::core::ptr::addr_of_mut!((*coder).check), + (*(*coder).block).check, + in_0.offset(in_start as isize), + in_used, + ); + } + if ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH { + return ret; + } + (*(*coder).block).compressed_size = (*coder).compressed_size; + (*(*coder).block).uncompressed_size = (*coder).uncompressed_size; + (*coder).sequence = SEQ_PADDING; + 6470892831169497455 + } + 1 => 6470892831169497455, + 2 => 47327340716975230, + _ => return LZMA_PROG_ERROR, + }; + if current_block_34 == 6470892831169497455 { + while (*coder).compressed_size & 3 != 0 { + if *out_pos >= out_size { + return LZMA_OK; + } + *out.offset(*out_pos as isize) = 0; + *out_pos += 1; + (*coder).compressed_size += 1; + } + if (*(*coder).block).check == LZMA_CHECK_NONE { + return LZMA_STREAM_END; + } + lzma_check_finish( + ::core::ptr::addr_of_mut!((*coder).check), + (*(*coder).block).check, + ); + (*coder).sequence = SEQ_CHECK; + } + let check_size: size_t = lzma_check_size((*(*coder).block).check) as size_t; + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).check.buffer.u8_0) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + check_size, + out, + out_pos, + out_size, + ); + if (*coder).pos < check_size { + return LZMA_OK; + } + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!((*coder).check.buffer.u8_0) as *const u8, + ::core::ptr::addr_of_mut!((*(*coder).block).raw_check) as *mut u8, + check_size, + ); + LZMA_STREAM_END +} +unsafe extern "C" fn block_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_block_coder = coder_ptr as *mut lzma_block_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn block_encoder_update( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + _filters: *const lzma_filter, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_block_coder = coder_ptr as *mut lzma_block_coder; + if (*coder).sequence != SEQ_CODE { + return LZMA_PROG_ERROR; + } + lzma_next_filter_update( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + reversed_filters, + ) +} +pub unsafe extern "C" fn lzma_block_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + block: *mut lzma_block, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_block_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_block_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut lzma_block, + ) -> lzma_ret, + )); + if block.is_null() { + return LZMA_PROG_ERROR; + } + if (*block).version > 1 { + return LZMA_OPTIONS_ERROR; + } + if (*block).check > LZMA_CHECK_ID_MAX { + return LZMA_PROG_ERROR; + } + if lzma_check_is_supported((*block).check) == 0 { + return LZMA_UNSUPPORTED_CHECK; + } + let mut coder: *mut lzma_block_coder = (*next).coder as *mut lzma_block_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + block_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + block_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).update = Some( + block_encoder_update + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + ); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + (*coder).sequence = SEQ_CODE; + (*coder).block = block; + (*coder).compressed_size = 0; + (*coder).uncompressed_size = 0; + (*coder).pos = 0; + lzma_check_init(::core::ptr::addr_of_mut!((*coder).check), (*block).check); + lzma_raw_encoder_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + (*block).filters, + ) +} +pub unsafe fn lzma_block_encoder(strm: *mut lzma_stream, block: *mut lzma_block) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_block_encoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + block, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_SYNC_FLUSH as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/block_header_decoder.rs b/liblzma-rs/src/common/block_header_decoder.rs new file mode 100644 index 00000000..11f63431 --- /dev/null +++ b/liblzma-rs/src/common/block_header_decoder.rs @@ -0,0 +1,87 @@ +use crate::common::filter_flags_decoder::lzma_filter_flags_decode; +use crate::types::*; +pub unsafe fn lzma_block_header_decode( + block: *mut lzma_block, + allocator: *const lzma_allocator, + in_0: *const u8, +) -> lzma_ret { + if block.is_null() || (*block).filters.is_null() || in_0.is_null() { + return LZMA_PROG_ERROR; + } + let mut i: size_t = 0; + while i <= LZMA_FILTERS_MAX as size_t { + (*(*block).filters.offset(i as isize)).id = LZMA_VLI_UNKNOWN; + (*(*block).filters.offset(i as isize)).options = core::ptr::null_mut(); + i += 1; + } + if (*block).version > 1 { + (*block).version = 1; + } + (*block).ignore_check = false as lzma_bool; + if (*in_0 as u32 + 1) * 4 != (*block).header_size || (*block).check > LZMA_CHECK_ID_MAX { + return LZMA_PROG_ERROR; + } + let in_size: size_t = ((*block).header_size - 4) as size_t; + if lzma_crc32(in_0, in_size, 0) != read32le(in_0.offset(in_size as isize)) { + return LZMA_DATA_ERROR; + } + if *in_0.offset(1) & 0x3c != 0 { + return LZMA_OPTIONS_ERROR; + } + let mut in_pos: size_t = 2; + if *in_0.offset(1) & 0x40 != 0 { + let ret_: lzma_ret = lzma_vli_decode( + ::core::ptr::addr_of_mut!((*block).compressed_size), + core::ptr::null_mut(), + in_0, + ::core::ptr::addr_of_mut!(in_pos), + in_size, + ); + if ret_ != LZMA_OK { + return ret_; + } + if lzma_block_unpadded_size(block) == 0 { + return LZMA_DATA_ERROR; + } + } else { + (*block).compressed_size = LZMA_VLI_UNKNOWN; + } + if *in_0.offset(1) & 0x80 != 0 { + let ret__0: lzma_ret = lzma_vli_decode( + ::core::ptr::addr_of_mut!((*block).uncompressed_size), + core::ptr::null_mut(), + in_0, + ::core::ptr::addr_of_mut!(in_pos), + in_size, + ); + if ret__0 != LZMA_OK { + return ret__0; + } + } else { + (*block).uncompressed_size = LZMA_VLI_UNKNOWN; + } + let filter_count: size_t = ((u32::from(*in_0.offset(1)) & 3) + 1) as size_t; + let mut i_0: size_t = 0; + while i_0 < filter_count { + let ret: lzma_ret = lzma_filter_flags_decode( + (*block).filters.offset(i_0 as isize) as *mut lzma_filter, + allocator, + in_0, + ::core::ptr::addr_of_mut!(in_pos), + in_size, + ); + if ret != LZMA_OK { + lzma_filters_free((*block).filters, allocator); + return ret; + } + i_0 += 1; + } + while in_pos < in_size { + if *in_0.offset(in_pos as isize) != 0 { + lzma_filters_free((*block).filters, allocator); + return LZMA_OPTIONS_ERROR; + } + in_pos += 1; + } + LZMA_OK +} diff --git a/liblzma-rs/src/common/block_header_encoder.rs b/liblzma-rs/src/common/block_header_encoder.rs new file mode 100644 index 00000000..f7ff43e4 --- /dev/null +++ b/liblzma-rs/src/common/block_header_encoder.rs @@ -0,0 +1,111 @@ +use crate::common::filter_flags_encoder::{lzma_filter_flags_encode, lzma_filter_flags_size}; +use crate::types::*; +pub unsafe fn lzma_block_header_size(block: *mut lzma_block) -> lzma_ret { + if (*block).version > 1 { + return LZMA_OPTIONS_ERROR; + } + let mut size: u32 = (1 + 1 + 4) as u32; + if (*block).compressed_size != LZMA_VLI_UNKNOWN { + let add: u32 = lzma_vli_size((*block).compressed_size) as u32; + if add == 0 || (*block).compressed_size == 0 { + return LZMA_PROG_ERROR; + } + size += add; + } + if (*block).uncompressed_size != LZMA_VLI_UNKNOWN { + let add_0: u32 = lzma_vli_size((*block).uncompressed_size) as u32; + if add_0 == 0 { + return LZMA_PROG_ERROR; + } + size += add_0; + } + if (*block).filters.is_null() || (*(*block).filters).id == LZMA_VLI_UNKNOWN { + return LZMA_PROG_ERROR; + } + let mut i: size_t = 0; + while (*(*block).filters.offset(i as isize)).id != LZMA_VLI_UNKNOWN { + if i == LZMA_FILTERS_MAX as size_t { + return LZMA_PROG_ERROR; + } + let mut add_1: u32 = 0; + let ret_: lzma_ret = lzma_filter_flags_size( + ::core::ptr::addr_of_mut!(add_1), + (*block).filters.offset(i as isize), + ); + if ret_ != LZMA_OK { + return ret_; + } + size += add_1; + i += 1; + } + (*block).header_size = (size + 3) & !(3); + LZMA_OK +} +pub unsafe fn lzma_block_header_encode(block: *const lzma_block, out: *mut u8) -> lzma_ret { + if lzma_block_unpadded_size(block) == 0 + || !((*block).uncompressed_size <= LZMA_VLI_MAX + || (*block).uncompressed_size == LZMA_VLI_UNKNOWN) + { + return LZMA_PROG_ERROR; + } + let out_size: size_t = ((*block).header_size - 4) as size_t; + *out = (out_size / 4) as u8; + *out.offset(1) = 0; + let mut out_pos: size_t = 2; + if (*block).compressed_size != LZMA_VLI_UNKNOWN { + let ret_: lzma_ret = lzma_vli_encode( + (*block).compressed_size, + core::ptr::null_mut(), + out, + ::core::ptr::addr_of_mut!(out_pos), + out_size, + ); + if ret_ != LZMA_OK { + return ret_; + } + *out.offset(1) |= 0x40; + } + if (*block).uncompressed_size != LZMA_VLI_UNKNOWN { + let ret__0: lzma_ret = lzma_vli_encode( + (*block).uncompressed_size, + core::ptr::null_mut(), + out, + ::core::ptr::addr_of_mut!(out_pos), + out_size, + ); + if ret__0 != LZMA_OK { + return ret__0; + } + *out.offset(1) |= 0x80; + } + if (*block).filters.is_null() || (*(*block).filters).id == LZMA_VLI_UNKNOWN { + return LZMA_PROG_ERROR; + } + let mut filter_count: size_t = 0; + loop { + if filter_count == LZMA_FILTERS_MAX as size_t { + return LZMA_PROG_ERROR; + } + let ret__1: lzma_ret = lzma_filter_flags_encode( + (*block).filters.offset(filter_count as isize), + out, + ::core::ptr::addr_of_mut!(out_pos), + out_size, + ); + if ret__1 != LZMA_OK { + return ret__1; + } + filter_count += 1; + if (*(*block).filters.offset(filter_count as isize)).id == LZMA_VLI_UNKNOWN { + break; + } + } + *out.offset(1) |= (filter_count - 1) as u8; + core::ptr::write_bytes( + out.offset(out_pos as isize) as *mut u8, + 0 as u8, + out_size - out_pos, + ); + write32le(out.offset(out_size as isize), lzma_crc32(out, out_size, 0)); + LZMA_OK +} diff --git a/liblzma-rs/src/common/block_util.rs b/liblzma-rs/src/common/block_util.rs new file mode 100644 index 00000000..6b47061f --- /dev/null +++ b/liblzma-rs/src/common/block_util.rs @@ -0,0 +1,51 @@ +use crate::types::*; +pub const LZMA_BLOCK_HEADER_SIZE_MIN: u32 = 8; +pub unsafe fn lzma_block_compressed_size( + block: *mut lzma_block, + unpadded_size: lzma_vli, +) -> lzma_ret { + if lzma_block_unpadded_size(block) == 0 { + return LZMA_PROG_ERROR; + } + let container_size: u32 = (*block).header_size + lzma_check_size((*block).check) as u32; + if unpadded_size <= container_size as lzma_vli { + return LZMA_DATA_ERROR; + } + let compressed_size: lzma_vli = unpadded_size - container_size as lzma_vli; + if (*block).compressed_size != LZMA_VLI_UNKNOWN && (*block).compressed_size != compressed_size { + return LZMA_DATA_ERROR; + } + (*block).compressed_size = compressed_size; + LZMA_OK +} +pub unsafe fn lzma_block_unpadded_size(block: *const lzma_block) -> lzma_vli { + if block.is_null() + || (*block).version > 1 + || (*block).header_size < LZMA_BLOCK_HEADER_SIZE_MIN + || (*block).header_size > LZMA_BLOCK_HEADER_SIZE_MAX + || (*block).header_size & 3 != 0 + || !((*block).compressed_size <= LZMA_VLI_MAX + || (*block).compressed_size == LZMA_VLI_UNKNOWN) + || (*block).compressed_size == 0 + || (*block).check > LZMA_CHECK_ID_MAX + { + return 0; + } + if (*block).compressed_size == LZMA_VLI_UNKNOWN { + return LZMA_VLI_UNKNOWN; + } + let unpadded_size: lzma_vli = (*block).compressed_size + + (*block).header_size as lzma_vli + + lzma_check_size((*block).check) as lzma_vli; + if unpadded_size > UNPADDED_SIZE_MAX { + return 0; + } + unpadded_size +} +pub unsafe fn lzma_block_total_size(block: *const lzma_block) -> lzma_vli { + let mut unpadded_size: lzma_vli = lzma_block_unpadded_size(block); + if unpadded_size != LZMA_VLI_UNKNOWN { + unpadded_size = vli_ceil4(unpadded_size); + } + unpadded_size +} diff --git a/liblzma-rs/src/common/common.rs b/liblzma-rs/src/common/common.rs new file mode 100644 index 00000000..cde83adb --- /dev/null +++ b/liblzma-rs/src/common/common.rs @@ -0,0 +1,478 @@ +use crate::types::*; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +use std::alloc::{alloc, alloc_zeroed, dealloc, Layout}; + +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +extern "C" { + fn malloc(__size: size_t) -> *mut c_void; + fn calloc(__count: size_t, __size: size_t) -> *mut c_void; + fn free(_: *mut c_void); +} + +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +const LZMA_ALLOC_ALIGN: usize = 16; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +const LZMA_ALLOC_HEADER_SIZE: usize = 16; + +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +unsafe fn rust_alloc_layout(size: usize) -> Option { + let total_size = size.checked_add(LZMA_ALLOC_HEADER_SIZE)?; + Layout::from_size_align(total_size, LZMA_ALLOC_ALIGN).ok() +} + +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +unsafe fn malloc(size: size_t) -> *mut c_void { + let layout = match rust_alloc_layout(size as usize) { + Some(layout) => layout, + None => return core::ptr::null_mut(), + }; + let base = alloc(layout); + if base.is_null() { + return core::ptr::null_mut(); + } + *(base as *mut usize) = layout.size(); + base.add(LZMA_ALLOC_HEADER_SIZE) as *mut c_void +} + +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +unsafe fn calloc(count: size_t, size: size_t) -> *mut c_void { + let size = match (count as usize).checked_mul(size as usize) { + Some(size) => size, + None => return core::ptr::null_mut(), + }; + let layout = match rust_alloc_layout(size) { + Some(layout) => layout, + None => return core::ptr::null_mut(), + }; + let base = alloc_zeroed(layout); + if base.is_null() { + return core::ptr::null_mut(); + } + *(base as *mut usize) = layout.size(); + base.add(LZMA_ALLOC_HEADER_SIZE) as *mut c_void +} + +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +unsafe fn free(ptr: *mut c_void) { + if ptr.is_null() { + return; + } + let base = (ptr as *mut u8).sub(LZMA_ALLOC_HEADER_SIZE); + let total_size = *(base as *const usize); + let layout = Layout::from_size_align_unchecked(total_size, LZMA_ALLOC_ALIGN); + dealloc(base, layout); +} +pub const LZMA_VERSION_MAJOR: u32 = 5; +pub const LZMA_VERSION_MINOR: u32 = 8; +pub const LZMA_VERSION_PATCH: u32 = 2; +pub const LZMA_VERSION_STABILITY: u32 = LZMA_VERSION_STABILITY_STABLE; +pub const LZMA_VERSION_STABILITY_STABLE: u32 = 2; +pub const LZMA_VERSION: c_uint = LZMA_VERSION_MAJOR * 10000000 + + LZMA_VERSION_MINOR * 10000 + + LZMA_VERSION_PATCH * 10 + + LZMA_VERSION_STABILITY; +pub const LZMA_TIMED_OUT: c_uint = 101; +pub fn lzma_version_number() -> u32 { + LZMA_VERSION as u32 +} +pub fn lzma_version_string() -> *const c_char { + crate::c_str!("5.8.2") +} +pub unsafe fn lzma_alloc(mut size: size_t, allocator: *const lzma_allocator) -> *mut c_void { + if size == 0 { + size = 1; + } + let mut ptr: *mut c_void = core::ptr::null_mut(); + if !allocator.is_null() && (*allocator).alloc.is_some() { + ptr = (*allocator).alloc.unwrap()((*allocator).opaque, 1, size); + } else { + ptr = malloc(size); + } + ptr +} +pub unsafe fn lzma_alloc_zero(mut size: size_t, allocator: *const lzma_allocator) -> *mut c_void { + if size == 0 { + size = 1; + } + let mut ptr: *mut c_void = core::ptr::null_mut(); + if !allocator.is_null() && (*allocator).alloc.is_some() { + ptr = (*allocator).alloc.unwrap()((*allocator).opaque, 1, size); + if !ptr.is_null() { + core::ptr::write_bytes(ptr as *mut u8, 0, size); + } + } else { + ptr = calloc(1, size); + } + ptr +} +pub unsafe extern "C" fn lzma_free(ptr: *mut c_void, allocator: *const lzma_allocator) { + if !allocator.is_null() && (*allocator).free.is_some() { + (*allocator).free.unwrap()((*allocator).opaque, ptr); + } else { + free(ptr); + }; +} +pub unsafe fn lzma_bufcpy( + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> size_t { + if *in_pos > in_size || *out_pos > out_size { + return 0; + } + + let in_avail: size_t = in_size - *in_pos; + let out_avail: size_t = out_size - *out_pos; + let copy_size: size_t = if in_avail < out_avail { + in_avail + } else { + out_avail + }; + if copy_size > 0 { + core::ptr::copy_nonoverlapping( + in_0.offset(*in_pos as isize) as *const u8, + out.offset(*out_pos as isize) as *mut u8, + copy_size, + ); + } + *in_pos += copy_size; + *out_pos += copy_size; + copy_size +} +pub unsafe fn lzma_next_filter_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + if core::mem::transmute::((*filters).init) != (*next).init { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::((*filters).init); + (*next).id = (*filters).id; + if (*filters).init.is_none() { + LZMA_OK + } else { + (*filters).init.unwrap()(next, allocator, filters) + } +} +pub unsafe fn lzma_next_filter_update( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + if (*reversed_filters).id != (*next).id { + return LZMA_PROG_ERROR; + } + if (*reversed_filters).id == LZMA_VLI_UNKNOWN { + return LZMA_OK; + } + let update = if let Some(update) = (*next).update { + update + } else { + return LZMA_PROG_ERROR; + }; + update( + (*next).coder, + allocator, + core::ptr::null(), + reversed_filters, + ) +} +pub unsafe fn lzma_next_end(next: *mut lzma_next_coder, allocator: *const lzma_allocator) { + if (*next).init != 0 { + if (*next).end.is_some() { + (*next).end.unwrap()((*next).coder, allocator); + } else { + lzma_free((*next).coder, allocator); + } + *next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } +} +pub unsafe fn lzma_strm_init(strm: *mut lzma_stream) -> lzma_ret { + if strm.is_null() { + return LZMA_PROG_ERROR; + } + if (*strm).internal.is_null() { + (*strm).internal = crate::alloc::internal_alloc_object::((*strm).allocator); + if (*strm).internal.is_null() { + return LZMA_MEM_ERROR; + } + (*(*strm).internal).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + core::ptr::write_bytes( + ::core::ptr::addr_of_mut!((*(*strm).internal).supported_actions) as *mut u8, + 0 as u8, + core::mem::size_of::<[bool; 5]>(), + ); + (*(*strm).internal).sequence = ISEQ_RUN; + (*(*strm).internal).allow_buf_error = false; + (*(*strm).internal).avail_in = 0; + (*strm).total_in = 0; + (*strm).total_out = 0; + LZMA_OK +} +pub unsafe fn lzma_code(strm: *mut lzma_stream, action: lzma_action) -> lzma_ret { + if (*strm).next_in.is_null() && (*strm).avail_in != 0 + || (*strm).next_out.is_null() && (*strm).avail_out != 0 + || (*strm).internal.is_null() + || (*(*strm).internal).next.code.is_none() + || action > LZMA_FULL_BARRIER + || !(*(*strm).internal).supported_actions[action as usize] + { + return LZMA_PROG_ERROR; + } + if !(*strm).reserved_ptr1.is_null() + || !(*strm).reserved_ptr2.is_null() + || !(*strm).reserved_ptr3.is_null() + || !(*strm).reserved_ptr4.is_null() + || (*strm).reserved_int2 != 0 + || (*strm).reserved_int3 != 0 + || (*strm).reserved_int4 != 0 + || (*strm).reserved_enum1 != LZMA_RESERVED_ENUM + || (*strm).reserved_enum2 != LZMA_RESERVED_ENUM + { + return LZMA_OPTIONS_ERROR; + } + match (*(*strm).internal).sequence { + 0 => match action { + 1 => { + (*(*strm).internal).sequence = ISEQ_SYNC_FLUSH; + } + 2 => { + (*(*strm).internal).sequence = ISEQ_FULL_FLUSH; + } + 3 => { + (*(*strm).internal).sequence = ISEQ_FINISH; + } + 4 => { + (*(*strm).internal).sequence = ISEQ_FULL_BARRIER; + } + 0 | _ => {} + }, + 1 => { + if action != LZMA_SYNC_FLUSH || (*(*strm).internal).avail_in != (*strm).avail_in { + return LZMA_PROG_ERROR; + } + } + 2 => { + if action != LZMA_FULL_FLUSH || (*(*strm).internal).avail_in != (*strm).avail_in { + return LZMA_PROG_ERROR; + } + } + 3 => { + if action != LZMA_FINISH || (*(*strm).internal).avail_in != (*strm).avail_in { + return LZMA_PROG_ERROR; + } + } + 4 => { + if action != LZMA_FULL_BARRIER || (*(*strm).internal).avail_in != (*strm).avail_in { + return LZMA_PROG_ERROR; + } + } + 5 => return LZMA_STREAM_END, + 6 | _ => return LZMA_PROG_ERROR, + } + let mut in_pos: size_t = 0; + let mut out_pos: size_t = 0; + let mut ret: lzma_ret = (*(*strm).internal).next.code.unwrap()( + (*(*strm).internal).next.coder, + (*strm).allocator, + (*strm).next_in, + ::core::ptr::addr_of_mut!(in_pos), + (*strm).avail_in, + (*strm).next_out, + ::core::ptr::addr_of_mut!(out_pos), + (*strm).avail_out, + action, + ); + if in_pos > 0 { + (*strm).next_in = (*strm).next_in.offset(in_pos as isize); + (*strm).avail_in -= in_pos; + (*strm).total_in = (*strm).total_in.wrapping_add(in_pos as u64); + } + if out_pos > 0 { + (*strm).next_out = (*strm).next_out.offset(out_pos as isize); + (*strm).avail_out -= out_pos; + (*strm).total_out = (*strm).total_out.wrapping_add(out_pos as u64); + } + (*(*strm).internal).avail_in = (*strm).avail_in; + let current_block_49: u64; + match ret { + 0 => { + if out_pos == 0 && in_pos == 0 { + if (*(*strm).internal).allow_buf_error { + ret = LZMA_BUF_ERROR; + } else { + (*(*strm).internal).allow_buf_error = true; + } + } else { + (*(*strm).internal).allow_buf_error = false; + } + current_block_49 = 12556861819962772176; + } + 101 => { + (*(*strm).internal).allow_buf_error = false; + ret = LZMA_OK; + current_block_49 = 12556861819962772176; + } + 12 => { + (*(*strm).internal).allow_buf_error = false; + if (*(*strm).internal).sequence == ISEQ_FINISH { + (*(*strm).internal).sequence = ISEQ_RUN; + } + current_block_49 = 12556861819962772176; + } + 1 => { + if (*(*strm).internal).sequence == ISEQ_SYNC_FLUSH + || (*(*strm).internal).sequence == ISEQ_FULL_FLUSH + || (*(*strm).internal).sequence == ISEQ_FULL_BARRIER + { + (*(*strm).internal).sequence = ISEQ_RUN; + } else { + (*(*strm).internal).sequence = ISEQ_END; + } + current_block_49 = 16143107162343188004; + } + 2 | 3 | 4 | 6 => { + current_block_49 = 16143107162343188004; + } + _ => { + (*(*strm).internal).sequence = ISEQ_ERROR; + current_block_49 = 12556861819962772176; + } + } + match current_block_49 { + 16143107162343188004 => { + (*(*strm).internal).allow_buf_error = false; + } + _ => {} + } + ret +} +pub unsafe fn lzma_end(strm: *mut lzma_stream) { + if !strm.is_null() && !(*strm).internal.is_null() { + lzma_next_end( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + ); + crate::alloc::internal_free((*strm).internal as *mut c_void, (*strm).allocator); + (*strm).internal = core::ptr::null_mut(); + } +} +pub unsafe fn lzma_get_progress( + strm: *mut lzma_stream, + progress_in: *mut u64, + progress_out: *mut u64, +) { + if strm.is_null() || (*strm).internal.is_null() { + if !progress_in.is_null() { + *progress_in = 0; + } + if !progress_out.is_null() { + *progress_out = 0; + } + return; + } + + if (*(*strm).internal).next.get_progress.is_some() { + (*(*strm).internal).next.get_progress.unwrap()( + (*(*strm).internal).next.coder, + progress_in, + progress_out, + ); + } else { + *progress_in = (*strm).total_in; + *progress_out = (*strm).total_out; + }; +} +pub fn lzma_get_check(strm: *const lzma_stream) -> lzma_check { + return unsafe { + if strm.is_null() || (*strm).internal.is_null() { + return LZMA_CHECK_NONE; + } + if (*(*strm).internal).next.get_check.is_none() { + return LZMA_CHECK_NONE; + } + (*(*strm).internal).next.get_check.unwrap()((*(*strm).internal).next.coder) + }; +} +pub fn lzma_memusage(strm: *const lzma_stream) -> u64 { + return unsafe { + let mut memusage: u64 = 0; + let mut old_memlimit: u64 = 0; + if strm.is_null() + || (*strm).internal.is_null() + || (*(*strm).internal).next.memconfig.is_none() + || (*(*strm).internal).next.memconfig.unwrap()( + (*(*strm).internal).next.coder, + ::core::ptr::addr_of_mut!(memusage), + ::core::ptr::addr_of_mut!(old_memlimit), + 0, + ) != LZMA_OK + { + return 0; + } + memusage + }; +} +pub fn lzma_memlimit_get(strm: *const lzma_stream) -> u64 { + return unsafe { + let mut old_memlimit: u64 = 0; + let mut memusage: u64 = 0; + if strm.is_null() + || (*strm).internal.is_null() + || (*(*strm).internal).next.memconfig.is_none() + || (*(*strm).internal).next.memconfig.unwrap()( + (*(*strm).internal).next.coder, + ::core::ptr::addr_of_mut!(memusage), + ::core::ptr::addr_of_mut!(old_memlimit), + 0, + ) != LZMA_OK + { + return 0; + } + old_memlimit + }; +} +pub unsafe fn lzma_memlimit_set(strm: *mut lzma_stream, mut new_memlimit: u64) -> lzma_ret { + let mut old_memlimit: u64 = 0; + let mut memusage: u64 = 0; + if strm.is_null() || (*strm).internal.is_null() || (*(*strm).internal).next.memconfig.is_none() + { + return LZMA_PROG_ERROR; + } + if new_memlimit == 0 { + new_memlimit = 1; + } + (*(*strm).internal).next.memconfig.unwrap()( + (*(*strm).internal).next.coder, + ::core::ptr::addr_of_mut!(memusage), + ::core::ptr::addr_of_mut!(old_memlimit), + new_memlimit, + ) +} diff --git a/liblzma-rs/src/common/easy_buffer_encoder.rs b/liblzma-rs/src/common/easy_buffer_encoder.rs new file mode 100644 index 00000000..74863c48 --- /dev/null +++ b/liblzma-rs/src/common/easy_buffer_encoder.rs @@ -0,0 +1,58 @@ +use crate::common::stream_buffer_encoder::lzma_stream_buffer_encode; +use crate::types::*; +pub unsafe fn lzma_easy_buffer_encode( + preset: u32, + check: lzma_check, + allocator: *const lzma_allocator, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + let mut opt_easy: lzma_options_easy = lzma_options_easy { + filters: [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5], + opt_lzma: lzma_options_lzma { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }, + }; + if lzma_easy_preset(::core::ptr::addr_of_mut!(opt_easy), preset) { + return LZMA_OPTIONS_ERROR; + } + lzma_stream_buffer_encode( + ::core::ptr::addr_of_mut!(opt_easy.filters) as *mut lzma_filter, + check, + allocator, + in_0, + in_size, + out, + out_pos, + out_size, + ) +} diff --git a/liblzma-rs/src/common/easy_decoder_memusage.rs b/liblzma-rs/src/common/easy_decoder_memusage.rs new file mode 100644 index 00000000..556efa9d --- /dev/null +++ b/liblzma-rs/src/common/easy_decoder_memusage.rs @@ -0,0 +1,41 @@ +use crate::types::*; +pub fn lzma_easy_decoder_memusage(preset: u32) -> u64 { + let mut opt_easy: lzma_options_easy = lzma_options_easy { + filters: [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5], + opt_lzma: lzma_options_lzma { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }, + }; + if unsafe { lzma_easy_preset(::core::ptr::addr_of_mut!(opt_easy), preset) } { + return UINT32_MAX as u64; + } + unsafe { + lzma_raw_decoder_memusage(::core::ptr::addr_of_mut!(opt_easy.filters) as *mut lzma_filter) + } +} diff --git a/liblzma-rs/src/common/easy_encoder.rs b/liblzma-rs/src/common/easy_encoder.rs new file mode 100644 index 00000000..4ed491e4 --- /dev/null +++ b/liblzma-rs/src/common/easy_encoder.rs @@ -0,0 +1,48 @@ +use crate::common::stream_encoder::lzma_stream_encoder; +use crate::types::*; +pub unsafe fn lzma_easy_encoder( + strm: *mut lzma_stream, + preset: u32, + check: lzma_check, +) -> lzma_ret { + let mut opt_easy: lzma_options_easy = lzma_options_easy { + filters: [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5], + opt_lzma: lzma_options_lzma { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }, + }; + if lzma_easy_preset(::core::ptr::addr_of_mut!(opt_easy), preset) { + return LZMA_OPTIONS_ERROR; + } + lzma_stream_encoder( + strm, + ::core::ptr::addr_of_mut!(opt_easy.filters) as *mut lzma_filter, + check, + ) +} diff --git a/liblzma-rs/src/common/easy_encoder_memusage.rs b/liblzma-rs/src/common/easy_encoder_memusage.rs new file mode 100644 index 00000000..029acdf3 --- /dev/null +++ b/liblzma-rs/src/common/easy_encoder_memusage.rs @@ -0,0 +1,41 @@ +use crate::types::*; +pub fn lzma_easy_encoder_memusage(preset: u32) -> u64 { + let mut opt_easy: lzma_options_easy = lzma_options_easy { + filters: [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5], + opt_lzma: lzma_options_lzma { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }, + }; + if unsafe { lzma_easy_preset(::core::ptr::addr_of_mut!(opt_easy), preset) } { + return UINT32_MAX as u64; + } + unsafe { + lzma_raw_encoder_memusage(::core::ptr::addr_of_mut!(opt_easy.filters) as *mut lzma_filter) + } +} diff --git a/liblzma-rs/src/common/easy_preset.rs b/liblzma-rs/src/common/easy_preset.rs new file mode 100644 index 00000000..fadc101d --- /dev/null +++ b/liblzma-rs/src/common/easy_preset.rs @@ -0,0 +1,10 @@ +use crate::types::*; +pub unsafe fn lzma_easy_preset(opt_easy: *mut lzma_options_easy, preset: u32) -> bool { + if lzma_lzma_preset(::core::ptr::addr_of_mut!((*opt_easy).opt_lzma), preset) != 0 { + return true; + } + (*opt_easy).filters[0].id = LZMA_FILTER_LZMA2; + (*opt_easy).filters[0].options = ::core::ptr::addr_of_mut!((*opt_easy).opt_lzma) as *mut c_void; + (*opt_easy).filters[1].id = LZMA_VLI_UNKNOWN; + false +} diff --git a/liblzma-rs/src/common/file_info.rs b/liblzma-rs/src/common/file_info.rs new file mode 100644 index 00000000..e9429322 --- /dev/null +++ b/liblzma-rs/src/common/file_info.rs @@ -0,0 +1,601 @@ +use crate::common::index::{ + lzma_index_cat, lzma_index_memused, lzma_index_stream_flags, lzma_index_stream_padding, + lzma_index_total_size, +}; +use crate::common::index_decoder::lzma_index_decoder_init; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_file_info_coder { + pub sequence: file_info_seq, + pub file_cur_pos: u64, + pub file_target_pos: u64, + pub file_size: u64, + pub index_decoder: lzma_next_coder, + pub index_remaining: lzma_vli, + pub this_index: *mut lzma_index, + pub stream_padding: lzma_vli, + pub combined_index: *mut lzma_index, + pub dest_index: *mut *mut lzma_index, + pub external_seek_pos: *mut u64, + pub memlimit: u64, + pub first_header_flags: lzma_stream_flags, + pub header_flags: lzma_stream_flags, + pub footer_flags: lzma_stream_flags, + pub temp_pos: size_t, + pub temp_size: size_t, + pub temp: [u8; 8192], +} +pub type file_info_seq = c_uint; +pub const SEQ_HEADER_COMPARE: file_info_seq = 7; +pub const SEQ_HEADER_DECODE: file_info_seq = 6; +pub const SEQ_INDEX_DECODE: file_info_seq = 5; +pub const SEQ_INDEX_INIT: file_info_seq = 4; +pub const SEQ_FOOTER: file_info_seq = 3; +pub const SEQ_PADDING_DECODE: file_info_seq = 2; +pub const SEQ_PADDING_SEEK: file_info_seq = 1; +pub const SEQ_MAGIC_BYTES: file_info_seq = 0; +unsafe fn fill_temp( + coder: *mut lzma_file_info_coder, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> bool { + (*coder).file_cur_pos += lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).temp) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).temp_pos), + (*coder).temp_size, + ) as u64; + (*coder).temp_pos < (*coder).temp_size +} +unsafe fn seek_to_pos( + coder: *mut lzma_file_info_coder, + target_pos: u64, + in_start: size_t, + in_pos: *mut size_t, + in_size: size_t, +) -> bool { + let pos_min: u64 = (*coder).file_cur_pos - (*in_pos - in_start) as u64; + let pos_max: u64 = (*coder).file_cur_pos + (in_size - *in_pos) as u64; + let mut external_seek_needed: bool = false; + if target_pos >= pos_min && target_pos <= pos_max { + *in_pos += (target_pos - (*coder).file_cur_pos) as size_t; + external_seek_needed = false; + } else { + *(*coder).external_seek_pos = target_pos; + external_seek_needed = true; + *in_pos = in_size; + } + (*coder).file_cur_pos = target_pos; + external_seek_needed +} +unsafe fn reverse_seek( + coder: *mut lzma_file_info_coder, + in_start: size_t, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + if (*coder).file_target_pos < (2 * LZMA_STREAM_HEADER_SIZE) as u64 { + return LZMA_DATA_ERROR; + } + (*coder).temp_pos = 0; + if ((*coder).file_target_pos - LZMA_STREAM_HEADER_SIZE as u64) + < core::mem::size_of::<[u8; 8192]>() as u64 + { + (*coder).temp_size = ((*coder).file_target_pos - LZMA_STREAM_HEADER_SIZE as u64) as size_t; + } else { + (*coder).temp_size = core::mem::size_of::<[u8; 8192]>() as size_t; + } + if seek_to_pos( + coder, + (*coder).file_target_pos - (*coder).temp_size as u64, + in_start, + in_pos, + in_size, + ) { + return LZMA_SEEK_NEEDED; + } + LZMA_OK +} +unsafe fn get_padding_size(buf: *const u8, mut buf_size: size_t) -> size_t { + let mut padding: size_t = 0; + while buf_size > 0 && { + buf_size -= 1; + *buf.offset(buf_size as isize) == 0 + } { + padding += 1; + } + padding +} +extern "C" fn hide_format_error(mut ret: lzma_ret) -> lzma_ret { + if ret == LZMA_FORMAT_ERROR { + ret = LZMA_DATA_ERROR; + } + ret +} +unsafe fn decode_index( + coder: *mut lzma_file_info_coder, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + update_file_cur_pos: bool, +) -> lzma_ret { + let in_start: size_t = *in_pos; + let ret: lzma_ret = (*coder).index_decoder.code.unwrap()( + (*coder).index_decoder.coder, + allocator, + in_0, + in_pos, + in_size, + core::ptr::null_mut(), + core::ptr::null_mut(), + 0, + LZMA_RUN, + ); + (*coder).index_remaining -= (*in_pos - in_start) as lzma_vli; + if update_file_cur_pos { + (*coder).file_cur_pos += (*in_pos - in_start) as u64; + } + ret +} +unsafe extern "C" fn file_info_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + mut in_size: size_t, + _out: *mut u8, + _out_pos: *mut size_t, + _out_size: size_t, + _action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_file_info_coder = coder_ptr as *mut lzma_file_info_coder; + let in_start: size_t = *in_pos; + if (*coder).file_size - (*coder).file_cur_pos < (in_size - in_start) as u64 { + in_size = in_start + ((*coder).file_size - (*coder).file_cur_pos) as size_t; + } + loop { + match (*coder).sequence { + SEQ_MAGIC_BYTES => { + if (*coder).file_size < LZMA_STREAM_HEADER_SIZE as u64 { + return LZMA_FORMAT_ERROR; + } + if fill_temp(coder, in_0, in_pos, in_size) { + return LZMA_OK; + } + let ret: lzma_ret = lzma_stream_header_decode( + ::core::ptr::addr_of_mut!((*coder).first_header_flags), + ::core::ptr::addr_of_mut!((*coder).temp) as *mut u8, + ); + if ret != LZMA_OK { + return ret; + } + if (*coder).file_size > LZMA_VLI_MAX as u64 || (*coder).file_size & 3 != 0 { + return LZMA_DATA_ERROR; + } + (*coder).file_target_pos = (*coder).file_size; + (*coder).sequence = SEQ_PADDING_SEEK; + } + SEQ_PADDING_SEEK => { + (*coder).sequence = SEQ_PADDING_DECODE; + let ret: lzma_ret = reverse_seek(coder, in_start, in_pos, in_size); + if ret != LZMA_OK { + return ret; + } + } + SEQ_PADDING_DECODE => { + if fill_temp(coder, in_0, in_pos, in_size) { + return LZMA_OK; + } + let new_padding: size_t = get_padding_size( + ::core::ptr::addr_of_mut!((*coder).temp) as *mut u8, + (*coder).temp_size, + ) as size_t; + (*coder).stream_padding += new_padding as lzma_vli; + (*coder).file_target_pos -= new_padding as u64; + if new_padding == (*coder).temp_size { + (*coder).sequence = SEQ_PADDING_SEEK; + continue; + } + if (*coder).stream_padding & 3 != 0 { + return LZMA_DATA_ERROR; + } + (*coder).sequence = SEQ_FOOTER; + (*coder).temp_size -= new_padding; + (*coder).temp_pos = (*coder).temp_size; + if (*coder).temp_size < LZMA_STREAM_HEADER_SIZE as size_t { + let ret: lzma_ret = reverse_seek(coder, in_start, in_pos, in_size); + if ret != LZMA_OK { + return ret; + } + } + } + SEQ_FOOTER => { + if fill_temp(coder, in_0, in_pos, in_size) { + return LZMA_OK; + } + (*coder).file_target_pos -= LZMA_STREAM_HEADER_SIZE as u64; + (*coder).temp_size -= LZMA_STREAM_HEADER_SIZE as size_t; + let ret: lzma_ret = hide_format_error(lzma_stream_footer_decode( + ::core::ptr::addr_of_mut!((*coder).footer_flags), + (::core::ptr::addr_of_mut!((*coder).temp) as *mut u8) + .offset((*coder).temp_size as isize), + )); + if ret != LZMA_OK { + return ret; + } + if (*coder).file_target_pos + < (*coder).footer_flags.backward_size + LZMA_STREAM_HEADER_SIZE as lzma_vli + { + return LZMA_DATA_ERROR; + } + (*coder).file_target_pos -= (*coder).footer_flags.backward_size as u64; + (*coder).sequence = SEQ_INDEX_INIT; + if (*coder).temp_size as lzma_vli >= (*coder).footer_flags.backward_size { + (*coder).temp_pos = ((*coder).temp_size as lzma_vli + - (*coder).footer_flags.backward_size) + as size_t; + } else { + (*coder).temp_pos = 0; + (*coder).temp_size = 0; + if seek_to_pos(coder, (*coder).file_target_pos, in_start, in_pos, in_size) { + return LZMA_SEEK_NEEDED; + } + } + } + SEQ_INDEX_INIT => { + let mut memused: u64 = 0; + if !(*coder).combined_index.is_null() { + memused = lzma_index_memused((*coder).combined_index); + if memused > (*coder).memlimit { + return LZMA_PROG_ERROR; + } + } + let ret: lzma_ret = lzma_index_decoder_init( + ::core::ptr::addr_of_mut!((*coder).index_decoder), + allocator, + ::core::ptr::addr_of_mut!((*coder).this_index), + (*coder).memlimit - memused, + ); + if ret != LZMA_OK { + return ret; + } + (*coder).index_remaining = (*coder).footer_flags.backward_size; + (*coder).sequence = SEQ_INDEX_DECODE; + } + SEQ_INDEX_DECODE => { + let ret: lzma_ret = if (*coder).temp_size != 0 { + decode_index( + coder, + allocator, + ::core::ptr::addr_of_mut!((*coder).temp) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).temp_pos), + (*coder).temp_size, + false, + ) + } else { + let mut in_stop: size_t = in_size; + if (in_size - *in_pos) as lzma_vli > (*coder).index_remaining { + in_stop = *in_pos + (*coder).index_remaining as size_t; + } + decode_index(coder, allocator, in_0, in_pos, in_stop, true) + }; + match ret { + LZMA_OK => { + if (*coder).index_remaining == 0 { + return LZMA_DATA_ERROR; + } + return LZMA_OK; + } + LZMA_STREAM_END => { + if (*coder).index_remaining != 0 { + return LZMA_DATA_ERROR; + } + } + _ => return ret, + } + let seek_amount: u64 = lzma_index_total_size((*coder).this_index) as u64 + + LZMA_STREAM_HEADER_SIZE as u64; + if (*coder).file_target_pos < seek_amount { + return LZMA_DATA_ERROR; + } + (*coder).file_target_pos -= seek_amount; + if (*coder).file_target_pos == 0 { + (*coder).header_flags = (*coder).first_header_flags; + (*coder).sequence = SEQ_HEADER_COMPARE; + continue; + } + (*coder).sequence = SEQ_HEADER_DECODE; + (*coder).file_target_pos += LZMA_STREAM_HEADER_SIZE as u64; + if (*coder).temp_size != 0 + && (*coder).temp_size as lzma_vli - (*coder).footer_flags.backward_size + >= seek_amount + { + (*coder).temp_pos = ((*coder).temp_size as lzma_vli + - (*coder).footer_flags.backward_size + - seek_amount as lzma_vli + + LZMA_STREAM_HEADER_SIZE as lzma_vli) + as size_t; + (*coder).temp_size = (*coder).temp_pos; + } else { + let ret_seek: lzma_ret = reverse_seek(coder, in_start, in_pos, in_size); + if ret_seek != LZMA_OK { + return ret_seek; + } + } + } + SEQ_HEADER_DECODE => { + if fill_temp(coder, in_0, in_pos, in_size) { + return LZMA_OK; + } + (*coder).file_target_pos -= LZMA_STREAM_HEADER_SIZE as u64; + (*coder).temp_size -= LZMA_STREAM_HEADER_SIZE as size_t; + (*coder).temp_pos = (*coder).temp_size; + let ret: lzma_ret = hide_format_error(lzma_stream_header_decode( + ::core::ptr::addr_of_mut!((*coder).header_flags), + (::core::ptr::addr_of_mut!((*coder).temp) as *mut u8) + .offset((*coder).temp_size as isize), + )); + if ret != LZMA_OK { + return ret; + } + (*coder).sequence = SEQ_HEADER_COMPARE; + } + SEQ_HEADER_COMPARE => { + let ret: lzma_ret = lzma_stream_flags_compare( + ::core::ptr::addr_of_mut!((*coder).header_flags), + ::core::ptr::addr_of_mut!((*coder).footer_flags), + ); + if ret != LZMA_OK { + return ret; + } + if lzma_index_stream_flags( + (*coder).this_index, + ::core::ptr::addr_of_mut!((*coder).footer_flags), + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + if lzma_index_stream_padding((*coder).this_index, (*coder).stream_padding) + != LZMA_OK + { + return LZMA_PROG_ERROR; + } + (*coder).stream_padding = 0; + if !(*coder).combined_index.is_null() { + let ret: lzma_ret = + lzma_index_cat((*coder).this_index, (*coder).combined_index, allocator); + if ret != LZMA_OK { + return ret; + } + } + (*coder).combined_index = (*coder).this_index; + (*coder).this_index = core::ptr::null_mut(); + if (*coder).file_target_pos == 0 { + *(*coder).dest_index = (*coder).combined_index; + (*coder).combined_index = core::ptr::null_mut(); + *in_pos = in_size; + return LZMA_STREAM_END; + } + (*coder).sequence = (if (*coder).temp_size > 0 { + SEQ_PADDING_DECODE + } else { + SEQ_PADDING_SEEK + }) as file_info_seq; + } + _ => return LZMA_PROG_ERROR, + } + } +} +unsafe extern "C" fn file_info_decoder_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_file_info_coder = coder_ptr as *mut lzma_file_info_coder; + let mut combined_index_memusage: u64 = 0; + let mut this_index_memusage: u64 = 0; + if !(*coder).combined_index.is_null() { + combined_index_memusage = lzma_index_memused((*coder).combined_index); + } + if !(*coder).this_index.is_null() { + this_index_memusage = lzma_index_memused((*coder).this_index); + } else if (*coder).sequence == SEQ_INDEX_DECODE { + let mut dummy: u64 = 0; + if (*coder).index_decoder.memconfig.unwrap()( + (*coder).index_decoder.coder, + ::core::ptr::addr_of_mut!(this_index_memusage), + ::core::ptr::addr_of_mut!(dummy), + 0, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + } + *memusage = combined_index_memusage + this_index_memusage; + if *memusage == 0 { + *memusage = lzma_index_memusage(1, 0); + } + *old_memlimit = (*coder).memlimit; + if new_memlimit != 0 { + if new_memlimit < *memusage { + return LZMA_MEMLIMIT_ERROR; + } + if (*coder).this_index.is_null() && (*coder).sequence == SEQ_INDEX_DECODE { + let idec_new_memlimit: u64 = new_memlimit - combined_index_memusage; + let mut dummy1: u64 = 0; + let mut dummy2: u64 = 0; + if (*coder).index_decoder.memconfig.unwrap()( + (*coder).index_decoder.coder, + ::core::ptr::addr_of_mut!(dummy1), + ::core::ptr::addr_of_mut!(dummy2), + idec_new_memlimit, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + } + (*coder).memlimit = new_memlimit; + } + LZMA_OK +} +unsafe extern "C" fn file_info_decoder_end( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, +) { + let coder: *mut lzma_file_info_coder = coder_ptr as *mut lzma_file_info_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).index_decoder), allocator); + lzma_index_end((*coder).this_index, allocator); + lzma_index_end((*coder).combined_index, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn lzma_file_info_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + seek_pos: *mut u64, + dest_index: *mut *mut lzma_index, + memlimit: u64, + file_size: u64, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut u64, + *mut *mut lzma_index, + u64, + u64, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_file_info_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut u64, + *mut *mut lzma_index, + u64, + u64, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut u64, + *mut *mut lzma_index, + u64, + u64, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_file_info_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut u64, + *mut *mut lzma_index, + u64, + u64, + ) -> lzma_ret, + )); + if dest_index.is_null() { + return LZMA_PROG_ERROR; + } + let mut coder: *mut lzma_file_info_coder = (*next).coder as *mut lzma_file_info_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + file_info_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + file_info_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).memconfig = Some( + file_info_decoder_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*coder).index_decoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).this_index = core::ptr::null_mut(); + (*coder).combined_index = core::ptr::null_mut(); + } + (*coder).sequence = SEQ_MAGIC_BYTES; + (*coder).file_cur_pos = 0; + (*coder).file_target_pos = 0; + (*coder).file_size = file_size; + lzma_index_end((*coder).this_index, allocator); + (*coder).this_index = core::ptr::null_mut(); + lzma_index_end((*coder).combined_index, allocator); + (*coder).combined_index = core::ptr::null_mut(); + (*coder).stream_padding = 0; + (*coder).dest_index = dest_index; + (*coder).external_seek_pos = seek_pos; + (*coder).memlimit = if 1 > memlimit { 1 } else { memlimit }; + (*coder).temp_pos = 0; + (*coder).temp_size = LZMA_STREAM_HEADER_SIZE as size_t; + LZMA_OK +} +pub unsafe fn lzma_file_info_decoder( + strm: *mut lzma_stream, + dest_index: *mut *mut lzma_index, + memlimit: u64, + file_size: u64, +) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_file_info_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + ::core::ptr::addr_of_mut!((*strm).seek_pos), + dest_index, + memlimit, + file_size, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/filter_buffer_decoder.rs b/liblzma-rs/src/common/filter_buffer_decoder.rs new file mode 100644 index 00000000..ebaf7e50 --- /dev/null +++ b/liblzma-rs/src/common/filter_buffer_decoder.rs @@ -0,0 +1,90 @@ +use crate::types::*; +pub unsafe fn lzma_raw_buffer_decode( + filters: *const lzma_filter, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if in_0.is_null() + || in_pos.is_null() + || *in_pos > in_size + || out.is_null() + || out_pos.is_null() + || *out_pos > out_size + { + return LZMA_PROG_ERROR; + } + let mut next: lzma_next_coder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + let ret_: lzma_ret = lzma_raw_decoder_init(::core::ptr::addr_of_mut!(next), allocator, filters); + if ret_ != LZMA_OK { + return ret_; + } + let code = if let Some(code) = next.code { + code + } else { + lzma_next_end(::core::ptr::addr_of_mut!(next), allocator); + return LZMA_PROG_ERROR; + }; + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + let mut ret: lzma_ret = code( + next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + LZMA_FINISH, + ); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + } else { + if ret == LZMA_OK { + if *in_pos != in_size { + ret = LZMA_BUF_ERROR; + } else if *out_pos != out_size { + ret = LZMA_DATA_ERROR; + } else { + let mut tmp: [u8; 1] = [0; 1]; + let mut tmp_pos: size_t = 0; + code( + next.coder, + allocator, + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!(tmp) as *mut u8, + ::core::ptr::addr_of_mut!(tmp_pos), + 1, + LZMA_FINISH, + ); + if tmp_pos == 1 { + ret = LZMA_BUF_ERROR; + } else { + ret = LZMA_DATA_ERROR; + } + } + } + *in_pos = in_start; + *out_pos = out_start; + } + lzma_next_end(::core::ptr::addr_of_mut!(next), allocator); + ret +} diff --git a/liblzma-rs/src/common/filter_buffer_encoder.rs b/liblzma-rs/src/common/filter_buffer_encoder.rs new file mode 100644 index 00000000..f088a2ee --- /dev/null +++ b/liblzma-rs/src/common/filter_buffer_encoder.rs @@ -0,0 +1,59 @@ +use crate::types::*; +pub unsafe fn lzma_raw_buffer_encode( + filters: *const lzma_filter, + allocator: *const lzma_allocator, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if in_0.is_null() && in_size != 0 || out.is_null() || out_pos.is_null() || *out_pos > out_size { + return LZMA_PROG_ERROR; + } + let mut next: lzma_next_coder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + let ret_: lzma_ret = lzma_raw_encoder_init(::core::ptr::addr_of_mut!(next), allocator, filters); + if ret_ != LZMA_OK { + return ret_; + } + let code = if let Some(code) = next.code { + code + } else { + lzma_next_end(::core::ptr::addr_of_mut!(next), allocator); + return LZMA_PROG_ERROR; + }; + let out_start: size_t = *out_pos; + let mut in_pos: size_t = 0; + let mut ret: lzma_ret = code( + next.coder, + allocator, + in_0, + ::core::ptr::addr_of_mut!(in_pos), + in_size, + out, + out_pos, + out_size, + LZMA_FINISH, + ); + lzma_next_end(::core::ptr::addr_of_mut!(next), allocator); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + } else { + if ret == LZMA_OK { + ret = LZMA_BUF_ERROR; + } + *out_pos = out_start; + } + ret +} diff --git a/liblzma-rs/src/common/filter_common.rs b/liblzma-rs/src/common/filter_common.rs new file mode 100644 index 00000000..2c39b69f --- /dev/null +++ b/liblzma-rs/src/common/filter_common.rs @@ -0,0 +1,318 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct filter_features { + pub id: lzma_vli, + pub options_size: size_t, + pub non_last_ok: bool, + pub last_ok: bool, + pub changes_size: bool, +} +static FEATURES: [filter_features; 13] = [ + filter_features { + id: LZMA_FILTER_LZMA1, + options_size: core::mem::size_of::(), + non_last_ok: false, + last_ok: true, + changes_size: true, + }, + filter_features { + id: LZMA_FILTER_LZMA1EXT, + options_size: core::mem::size_of::(), + non_last_ok: false, + last_ok: true, + changes_size: true, + }, + filter_features { + id: LZMA_FILTER_LZMA2, + options_size: core::mem::size_of::(), + non_last_ok: false, + last_ok: true, + changes_size: true, + }, + filter_features { + id: LZMA_FILTER_X86, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_POWERPC, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_IA64, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_ARM, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_ARMTHUMB, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_ARM64, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_SPARC, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_RISCV, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_FILTER_DELTA, + options_size: core::mem::size_of::(), + non_last_ok: true, + last_ok: false, + changes_size: false, + }, + filter_features { + id: LZMA_VLI_UNKNOWN, + options_size: 0, + non_last_ok: false, + last_ok: false, + changes_size: false, + }, +]; +pub unsafe fn lzma_filters_copy( + src: *const lzma_filter, + real_dest: *mut lzma_filter, + allocator: *const lzma_allocator, +) -> lzma_ret { + let current_block: u64; + if src.is_null() || real_dest.is_null() { + return LZMA_PROG_ERROR; + } + let mut dest: [lzma_filter; 5] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5]; + let mut ret: lzma_ret = LZMA_OK; + let mut i: size_t = 0; + i = 0; + 's_15: loop { + if (*src.offset(i as isize)).id == LZMA_VLI_UNKNOWN { + current_block = 7175849428784450219; + break; + } + if i == LZMA_FILTERS_MAX as size_t { + ret = LZMA_OPTIONS_ERROR; + current_block = 6392083060350426025; + break; + } else { + dest[i as usize].id = (*src.offset(i as isize)).id; + if (*src.offset(i as isize)).options.is_null() { + dest[i as usize].options = core::ptr::null_mut(); + } else { + let mut j: size_t = 0; + j = 0; + while (*src.offset(i as isize)).id != FEATURES[j as usize].id { + if FEATURES[j as usize].id == LZMA_VLI_UNKNOWN { + ret = LZMA_OPTIONS_ERROR; + current_block = 6392083060350426025; + break 's_15; + } else { + j += 1; + } + } + dest[i as usize].options = lzma_alloc(FEATURES[j as usize].options_size, allocator); + if dest[i as usize].options.is_null() { + ret = LZMA_MEM_ERROR; + current_block = 6392083060350426025; + break; + } else { + core::ptr::copy_nonoverlapping( + (*src.offset(i as isize)).options as *const u8, + dest[i as usize].options as *mut u8, + FEATURES[j as usize].options_size, + ); + } + } + i += 1; + } + } + match current_block { + 6392083060350426025 => { + while i > 0 { + i -= 1; + lzma_free(dest[i as usize].options, allocator); + } + return ret; + } + _ => { + dest[i as usize].id = LZMA_VLI_UNKNOWN; + dest[i as usize].options = core::ptr::null_mut(); + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!(dest) as *const u8, + real_dest as *mut u8, + (i + 1) * core::mem::size_of::(), + ); + return LZMA_OK; + } + }; +} +pub unsafe fn lzma_filters_free(filters: *mut lzma_filter, allocator: *const lzma_allocator) { + if filters.is_null() { + return; + } + let mut i: size_t = 0; + while (*filters.offset(i as isize)).id != LZMA_VLI_UNKNOWN { + if i == LZMA_FILTERS_MAX as size_t { + break; + } + lzma_free((*filters.offset(i as isize)).options, allocator); + (*filters.offset(i as isize)).options = core::ptr::null_mut(); + (*filters.offset(i as isize)).id = LZMA_VLI_UNKNOWN; + i += 1; + } +} +pub unsafe fn lzma_validate_chain(filters: *const lzma_filter, count: *mut size_t) -> lzma_ret { + if filters.is_null() || (*filters).id == LZMA_VLI_UNKNOWN { + return LZMA_PROG_ERROR; + } + let mut changes_size_count: size_t = 0; + let mut non_last_ok: bool = true; + let mut last_ok: bool = false; + let mut i: size_t = 0; + loop { + let mut j: size_t = 0; + j = 0; + while (*filters.offset(i as isize)).id != FEATURES[j as usize].id { + if FEATURES[j as usize].id == LZMA_VLI_UNKNOWN { + return LZMA_OPTIONS_ERROR; + } + j += 1; + } + if !non_last_ok { + return LZMA_OPTIONS_ERROR; + } + non_last_ok = FEATURES[j as usize].non_last_ok; + last_ok = FEATURES[j as usize].last_ok; + changes_size_count += FEATURES[j as usize].changes_size as size_t; + i += 1; + if (*filters.offset(i as isize)).id == LZMA_VLI_UNKNOWN { + break; + } + } + if i > LZMA_FILTERS_MAX as size_t || !last_ok || changes_size_count > 3 { + return LZMA_OPTIONS_ERROR; + } + *count = i; + LZMA_OK +} +pub unsafe fn lzma_raw_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + options: *const lzma_filter, + coder_find: lzma_filter_find, + is_encoder: bool, +) -> lzma_ret { + let mut count: size_t = 0; + let ret_: lzma_ret = lzma_validate_chain(options, ::core::ptr::addr_of_mut!(count)); + if ret_ != LZMA_OK { + return ret_; + } + let mut filters: [lzma_filter_info; 5] = [lzma_filter_info_s { + id: 0, + init: None, + options: core::ptr::null_mut(), + }; 5]; + if is_encoder { + let mut i: size_t = 0; + while i < count { + let j: size_t = count - i - 1; + let fc: *const lzma_filter_coder = + coder_find.unwrap()((*options.offset(i as isize)).id) as *const lzma_filter_coder; + if fc.is_null() || (*fc).init.is_none() { + return LZMA_OPTIONS_ERROR; + } + filters[j as usize].id = (*options.offset(i as isize)).id; + filters[j as usize].init = (*fc).init; + filters[j as usize].options = (*options.offset(i as isize)).options; + i += 1; + } + } else { + let mut i_0: size_t = 0; + while i_0 < count { + let fc_0: *const lzma_filter_coder = + coder_find.unwrap()((*options.offset(i_0 as isize)).id) as *const lzma_filter_coder; + if fc_0.is_null() || (*fc_0).init.is_none() { + return LZMA_OPTIONS_ERROR; + } + filters[i_0 as usize].id = (*options.offset(i_0 as isize)).id; + filters[i_0 as usize].init = (*fc_0).init; + filters[i_0 as usize].options = (*options.offset(i_0 as isize)).options; + i_0 += 1; + } + } + filters[count as usize].id = LZMA_VLI_UNKNOWN; + filters[count as usize].init = None; + let ret: lzma_ret = lzma_next_filter_init( + next, + allocator, + ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter_info, + ); + if ret != LZMA_OK { + lzma_next_end(next, allocator); + } + ret +} +pub unsafe fn lzma_raw_coder_memusage( + coder_find: lzma_filter_find, + filters: *const lzma_filter, +) -> u64 { + let mut tmp: size_t = 0; + if lzma_validate_chain(filters, ::core::ptr::addr_of_mut!(tmp)) != LZMA_OK { + return UINT64_MAX; + } + let mut total: u64 = 0; + let mut i: size_t = 0; + loop { + let fc: *const lzma_filter_coder = + coder_find.unwrap()((*filters.offset(i as isize)).id) as *const lzma_filter_coder; + if fc.is_null() { + return UINT64_MAX; + } + if (*fc).memusage.is_none() { + total += 1024; + } else { + let usage: u64 = (*fc).memusage.unwrap()((*filters.offset(i as isize)).options) as u64; + if usage == UINT64_MAX { + return UINT64_MAX; + } + total += usage; + } + i += 1; + if (*filters.offset(i as isize)).id == LZMA_VLI_UNKNOWN { + break; + } + } + total + LZMA_MEMUSAGE_BASE +} diff --git a/liblzma-rs/src/common/filter_decoder.rs b/liblzma-rs/src/common/filter_decoder.rs new file mode 100644 index 00000000..fa841b36 --- /dev/null +++ b/liblzma-rs/src/common/filter_decoder.rs @@ -0,0 +1,364 @@ +use crate::delta::delta_decoder::{lzma_delta_decoder_init, lzma_delta_props_decode}; +use crate::lzma::lzma2_decoder::{ + lzma_lzma2_decoder_init, lzma_lzma2_decoder_memusage, lzma_lzma2_props_decode, +}; +use crate::lzma::lzma_decoder::{lzma_lzma_decoder_memusage, lzma_lzma_props_decode}; +use crate::simple::arm::lzma_simple_arm_decoder_init; +use crate::simple::arm64::lzma_simple_arm64_decoder_init; +use crate::simple::armthumb::lzma_simple_armthumb_decoder_init; +use crate::simple::ia64::lzma_simple_ia64_decoder_init; +use crate::simple::powerpc::lzma_simple_powerpc_decoder_init; +use crate::simple::riscv::lzma_simple_riscv_decoder_init; +use crate::simple::simple_decoder::lzma_simple_props_decode; +use crate::simple::sparc::lzma_simple_sparc_decoder_init; +use crate::simple::x86::lzma_simple_x86_decoder_init; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_filter_decoder { + pub id: lzma_vli, + pub init: lzma_init_function, + pub memusage: Option u64>, + pub props_decode: Option< + unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + >, +} +static decoders: [lzma_filter_decoder; 12] = [ + lzma_filter_decoder { + id: LZMA_FILTER_LZMA1, + init: Some( + lzma_lzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_lzma_decoder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + props_decode: Some( + lzma_lzma_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_LZMA1EXT, + init: Some( + lzma_lzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_lzma_decoder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + props_decode: Some( + lzma_lzma_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_LZMA2, + init: Some( + lzma_lzma2_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_lzma2_decoder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + props_decode: Some( + lzma_lzma2_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_X86, + init: Some( + lzma_simple_x86_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_POWERPC, + init: Some( + lzma_simple_powerpc_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_IA64, + init: Some( + lzma_simple_ia64_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_ARM, + init: Some( + lzma_simple_arm_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_ARMTHUMB, + init: Some( + lzma_simple_armthumb_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_ARM64, + init: Some( + lzma_simple_arm64_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_SPARC, + init: Some( + lzma_simple_sparc_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_RISCV, + init: Some( + lzma_simple_riscv_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + props_decode: Some( + lzma_simple_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, + lzma_filter_decoder { + id: LZMA_FILTER_DELTA, + init: Some( + lzma_delta_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_delta_coder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + props_decode: Some( + lzma_delta_props_decode + as unsafe extern "C" fn( + *mut *mut c_void, + *const lzma_allocator, + *const u8, + size_t, + ) -> lzma_ret, + ), + }, +]; +extern "C" fn decoder_find(id: lzma_vli) -> *const lzma_filter_decoder { + let mut i: size_t = 0; + while i < core::mem::size_of::<[lzma_filter_decoder; 12]>() + / core::mem::size_of::() + { + if decoders[i as usize].id == id { + return &decoders[i as usize]; + } + i += 1; + } + core::ptr::null() +} +extern "C" fn coder_find(id: lzma_vli) -> *const lzma_filter_coder { + decoder_find(id) as *const lzma_filter_coder +} +pub fn lzma_filter_decoder_is_supported(id: lzma_vli) -> lzma_bool { + !decoder_find(id).is_null() as lzma_bool +} +pub unsafe fn lzma_raw_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + options: *const lzma_filter, +) -> lzma_ret { + lzma_raw_coder_init( + next, + allocator, + options, + Some(coder_find as unsafe extern "C" fn(lzma_vli) -> *const lzma_filter_coder), + false, + ) +} +pub unsafe fn lzma_raw_decoder(strm: *mut lzma_stream, options: *const lzma_filter) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_raw_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + options, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} +pub unsafe fn lzma_raw_decoder_memusage(filters: *const lzma_filter) -> u64 { + lzma_raw_coder_memusage( + Some(coder_find as unsafe extern "C" fn(lzma_vli) -> *const lzma_filter_coder), + filters, + ) +} +pub unsafe fn lzma_properties_decode( + filter: *mut lzma_filter, + allocator: *const lzma_allocator, + props: *const u8, + props_size: size_t, +) -> lzma_ret { + (*filter).options = core::ptr::null_mut(); + let fd: *const lzma_filter_decoder = decoder_find((*filter).id) as *const lzma_filter_decoder; + if fd.is_null() { + return LZMA_OPTIONS_ERROR; + } + if (*fd).props_decode.is_none() { + return if props_size == 0 { + LZMA_OK + } else { + LZMA_OPTIONS_ERROR + }; + } + (*fd).props_decode.unwrap()( + ::core::ptr::addr_of_mut!((*filter).options), + allocator, + props, + props_size, + ) +} diff --git a/liblzma-rs/src/common/filter_encoder.rs b/liblzma-rs/src/common/filter_encoder.rs new file mode 100644 index 00000000..82deffa9 --- /dev/null +++ b/liblzma-rs/src/common/filter_encoder.rs @@ -0,0 +1,398 @@ +use crate::delta::delta_encoder::{lzma_delta_encoder_init, lzma_delta_props_encode}; +use crate::lzma::lzma2_encoder::{ + lzma_lzma2_block_size, lzma_lzma2_encoder_init, lzma_lzma2_encoder_memusage, + lzma_lzma2_props_encode, +}; +use crate::lzma::lzma_encoder::lzma_lzma_props_encode; +use crate::simple::arm::lzma_simple_arm_encoder_init; +use crate::simple::arm64::lzma_simple_arm64_encoder_init; +use crate::simple::armthumb::lzma_simple_armthumb_encoder_init; +use crate::simple::ia64::lzma_simple_ia64_encoder_init; +use crate::simple::powerpc::lzma_simple_powerpc_encoder_init; +use crate::simple::riscv::lzma_simple_riscv_encoder_init; +use crate::simple::simple_encoder::{lzma_simple_props_encode, lzma_simple_props_size}; +use crate::simple::sparc::lzma_simple_sparc_encoder_init; +use crate::simple::x86::lzma_simple_x86_encoder_init; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_filter_encoder { + pub id: lzma_vli, + pub init: lzma_init_function, + pub memusage: Option u64>, + pub block_size: Option u64>, + pub props_size_get: Option lzma_ret>, + pub props_size_fixed: u32, + pub props_encode: Option lzma_ret>, +} +static encoders: [lzma_filter_encoder; 12] = [ + lzma_filter_encoder { + id: LZMA_FILTER_LZMA1, + init: Some( + lzma_lzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_lzma_encoder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + block_size: None, + props_size_get: None, + props_size_fixed: 5, + props_encode: Some( + lzma_lzma_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_LZMA1EXT, + init: Some( + lzma_lzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_lzma_encoder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + block_size: None, + props_size_get: None, + props_size_fixed: 5, + props_encode: Some( + lzma_lzma_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_LZMA2, + init: Some( + lzma_lzma2_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_lzma2_encoder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + block_size: Some(lzma_lzma2_block_size as unsafe extern "C" fn(*const c_void) -> u64), + props_size_get: None, + props_size_fixed: 1, + props_encode: Some( + lzma_lzma2_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_X86, + init: Some( + lzma_simple_x86_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_POWERPC, + init: Some( + lzma_simple_powerpc_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_IA64, + init: Some( + lzma_simple_ia64_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_ARM, + init: Some( + lzma_simple_arm_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_ARMTHUMB, + init: Some( + lzma_simple_armthumb_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_ARM64, + init: Some( + lzma_simple_arm64_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_SPARC, + init: Some( + lzma_simple_sparc_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_RISCV, + init: Some( + lzma_simple_riscv_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: None, + block_size: None, + props_size_get: Some( + lzma_simple_props_size as unsafe extern "C" fn(*mut u32, *const c_void) -> lzma_ret, + ), + props_size_fixed: 0, + props_encode: Some( + lzma_simple_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, + lzma_filter_encoder { + id: LZMA_FILTER_DELTA, + init: Some( + lzma_delta_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + memusage: Some(lzma_delta_coder_memusage as unsafe extern "C" fn(*const c_void) -> u64), + block_size: None, + props_size_get: None, + props_size_fixed: 1, + props_encode: Some( + lzma_delta_props_encode as unsafe extern "C" fn(*const c_void, *mut u8) -> lzma_ret, + ), + }, +]; +extern "C" fn encoder_find(id: lzma_vli) -> *const lzma_filter_encoder { + let mut i: size_t = 0; + while i < core::mem::size_of::<[lzma_filter_encoder; 12]>() + / core::mem::size_of::() + { + if encoders[i as usize].id == id { + return &encoders[i as usize]; + } + i += 1; + } + core::ptr::null() +} +extern "C" fn coder_find(id: lzma_vli) -> *const lzma_filter_coder { + encoder_find(id) as *const lzma_filter_coder +} +pub fn lzma_filter_encoder_is_supported(id: lzma_vli) -> lzma_bool { + !encoder_find(id).is_null() as lzma_bool +} +pub unsafe fn lzma_filters_update(strm: *mut lzma_stream, filters: *const lzma_filter) -> lzma_ret { + if (*(*strm).internal).next.update.is_none() { + return LZMA_PROG_ERROR; + } + if lzma_raw_encoder_memusage(filters) == UINT64_MAX { + return LZMA_OPTIONS_ERROR; + } + let mut count: size_t = 1; + while (*filters.offset(count as isize)).id != LZMA_VLI_UNKNOWN { + count += 1; + } + let mut reversed_filters: [lzma_filter; 5] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5]; + let mut i: size_t = 0; + while i < count { + reversed_filters[count - i - 1] = *filters.offset(i as isize); + i += 1; + } + reversed_filters[count as usize].id = LZMA_VLI_UNKNOWN; + (*(*strm).internal).next.update.unwrap()( + (*(*strm).internal).next.coder, + (*strm).allocator, + filters, + ::core::ptr::addr_of_mut!(reversed_filters) as *mut lzma_filter, + ) +} +pub unsafe fn lzma_raw_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter, +) -> lzma_ret { + lzma_raw_coder_init( + next, + allocator, + filters, + Some(coder_find as unsafe extern "C" fn(lzma_vli) -> *const lzma_filter_coder), + true, + ) +} +pub unsafe fn lzma_raw_encoder(strm: *mut lzma_stream, filters: *const lzma_filter) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_raw_coder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + filters, + Some(coder_find as unsafe extern "C" fn(lzma_vli) -> *const lzma_filter_coder), + true, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_SYNC_FLUSH as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} +pub unsafe fn lzma_raw_encoder_memusage(filters: *const lzma_filter) -> u64 { + lzma_raw_coder_memusage( + Some(coder_find as unsafe extern "C" fn(lzma_vli) -> *const lzma_filter_coder), + filters, + ) +} +pub unsafe fn lzma_mt_block_size(filters: *const lzma_filter) -> u64 { + if filters.is_null() { + return UINT64_MAX; + } + let mut max: u64 = 0; + let mut i: size_t = 0; + while (*filters.offset(i as isize)).id != LZMA_VLI_UNKNOWN { + let fe: *const lzma_filter_encoder = + encoder_find((*filters.offset(i as isize)).id) as *const lzma_filter_encoder; + if fe.is_null() { + return UINT64_MAX; + } + if (*fe).block_size.is_some() { + let size: u64 = (*fe).block_size.unwrap()((*filters.offset(i as isize)).options) as u64; + if size > max { + max = size; + } + } + i += 1; + } + if max == 0 { + UINT64_MAX + } else { + max + } +} +pub unsafe fn lzma_properties_size(size: *mut u32, filter: *const lzma_filter) -> lzma_ret { + let fe: *const lzma_filter_encoder = encoder_find((*filter).id) as *const lzma_filter_encoder; + if fe.is_null() { + return if (*filter).id <= LZMA_VLI_MAX { + LZMA_OPTIONS_ERROR + } else { + LZMA_PROG_ERROR + }; + } + if (*fe).props_size_get.is_none() { + *size = (*fe).props_size_fixed; + return LZMA_OK; + } + (*fe).props_size_get.unwrap()(size, (*filter).options) +} +pub unsafe fn lzma_properties_encode(filter: *const lzma_filter, props: *mut u8) -> lzma_ret { + let fe: *const lzma_filter_encoder = encoder_find((*filter).id) as *const lzma_filter_encoder; + if fe.is_null() { + return LZMA_PROG_ERROR; + } + if (*fe).props_encode.is_none() { + return LZMA_OK; + } + (*fe).props_encode.unwrap()((*filter).options, props) +} diff --git a/liblzma-rs/src/common/filter_flags_decoder.rs b/liblzma-rs/src/common/filter_flags_decoder.rs new file mode 100644 index 00000000..926b5345 --- /dev/null +++ b/liblzma-rs/src/common/filter_flags_decoder.rs @@ -0,0 +1,46 @@ +use crate::common::filter_decoder::lzma_properties_decode; +use crate::types::*; +pub unsafe fn lzma_filter_flags_decode( + filter: *mut lzma_filter, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + (*filter).options = core::ptr::null_mut(); + let ret_: lzma_ret = lzma_vli_decode( + ::core::ptr::addr_of_mut!((*filter).id), + core::ptr::null_mut(), + in_0, + in_pos, + in_size, + ); + if ret_ != LZMA_OK { + return ret_; + } + if (*filter).id >= LZMA_FILTER_RESERVED_START { + return LZMA_DATA_ERROR; + } + let mut props_size: lzma_vli = 0; + let ret__0: lzma_ret = lzma_vli_decode( + ::core::ptr::addr_of_mut!(props_size), + core::ptr::null_mut(), + in_0, + in_pos, + in_size, + ); + if ret__0 != LZMA_OK { + return ret__0; + } + if ((in_size - *in_pos) as lzma_vli) < props_size { + return LZMA_DATA_ERROR; + } + let ret: lzma_ret = lzma_properties_decode( + filter, + allocator, + in_0.offset(*in_pos as isize), + props_size as size_t, + ); + *in_pos = (*in_pos as lzma_vli + props_size) as size_t; + ret +} diff --git a/liblzma-rs/src/common/filter_flags_encoder.rs b/liblzma-rs/src/common/filter_flags_encoder.rs new file mode 100644 index 00000000..cf96a80f --- /dev/null +++ b/liblzma-rs/src/common/filter_flags_encoder.rs @@ -0,0 +1,52 @@ +use crate::common::filter_encoder::{lzma_properties_encode, lzma_properties_size}; +use crate::types::*; +pub unsafe fn lzma_filter_flags_size(size: *mut u32, filter: *const lzma_filter) -> lzma_ret { + if (*filter).id >= LZMA_FILTER_RESERVED_START { + return LZMA_PROG_ERROR; + } + let ret_: lzma_ret = lzma_properties_size(size, filter); + if ret_ != LZMA_OK { + return ret_; + } + *size += lzma_vli_size((*filter).id) + lzma_vli_size(*size as lzma_vli); + LZMA_OK +} +pub unsafe fn lzma_filter_flags_encode( + filter: *const lzma_filter, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if (*filter).id >= LZMA_FILTER_RESERVED_START { + return LZMA_PROG_ERROR; + } + let ret_: lzma_ret = + lzma_vli_encode((*filter).id, core::ptr::null_mut(), out, out_pos, out_size); + if ret_ != LZMA_OK { + return ret_; + } + let mut props_size: u32 = 0; + let ret__0: lzma_ret = lzma_properties_size(::core::ptr::addr_of_mut!(props_size), filter); + if ret__0 != LZMA_OK { + return ret__0; + } + let ret__1: lzma_ret = lzma_vli_encode( + props_size as lzma_vli, + core::ptr::null_mut(), + out, + out_pos, + out_size, + ); + if ret__1 != LZMA_OK { + return ret__1; + } + if out_size - *out_pos < props_size as size_t { + return LZMA_PROG_ERROR; + } + let ret__2: lzma_ret = lzma_properties_encode(filter, out.offset(*out_pos as isize)); + if ret__2 != LZMA_OK { + return ret__2; + } + *out_pos += props_size as size_t; + LZMA_OK +} diff --git a/liblzma-rs/src/common/hardware_cputhreads.rs b/liblzma-rs/src/common/hardware_cputhreads.rs new file mode 100644 index 00000000..73fe4665 --- /dev/null +++ b/liblzma-rs/src/common/hardware_cputhreads.rs @@ -0,0 +1,4 @@ +use crate::tuklib::tuklib_cpucores::tuklib_cpucores; +pub fn lzma_cputhreads() -> u32 { + tuklib_cpucores() +} diff --git a/liblzma-rs/src/common/hardware_physmem.rs b/liblzma-rs/src/common/hardware_physmem.rs new file mode 100644 index 00000000..9cf32319 --- /dev/null +++ b/liblzma-rs/src/common/hardware_physmem.rs @@ -0,0 +1,4 @@ +use crate::tuklib::tuklib_physmem::tuklib_physmem; +pub fn lzma_physmem() -> u64 { + tuklib_physmem() +} diff --git a/liblzma-rs/src/common/index.rs b/liblzma-rs/src/common/index.rs new file mode 100644 index 00000000..079c06bc --- /dev/null +++ b/liblzma-rs/src/common/index.rs @@ -0,0 +1,889 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_s { + pub streams: index_tree, + pub uncompressed_size: lzma_vli, + pub total_size: lzma_vli, + pub record_count: lzma_vli, + pub index_list_size: lzma_vli, + pub prealloc: size_t, + pub checks: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct index_tree { + pub root: *mut index_tree_node, + pub leftmost: *mut index_tree_node, + pub rightmost: *mut index_tree_node, + pub count: u32, +} +pub type index_tree_node = index_tree_node_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct index_tree_node_s { + pub uncompressed_base: lzma_vli, + pub compressed_base: lzma_vli, + pub parent: *mut index_tree_node, + pub left: *mut index_tree_node, + pub right: *mut index_tree_node, +} +pub type lzma_index = lzma_index_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct index_record { + pub uncompressed_sum: lzma_vli, + pub unpadded_sum: lzma_vli, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct index_group { + pub node: index_tree_node, + pub number_base: lzma_vli, + pub allocated: size_t, + pub last: size_t, + pub records: [index_record; 0], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct index_stream { + pub node: index_tree_node, + pub number: u32, + pub block_number_base: lzma_vli, + pub groups: index_tree, + pub record_count: lzma_vli, + pub index_list_size: lzma_vli, + pub stream_flags: lzma_stream_flags, + pub stream_padding: lzma_vli, +} +pub const ITER_METHOD_NORMAL: iter_method = 0; +pub const ITER_METHOD: iter_mode = 4; +pub const ITER_RECORD: iter_mode = 3; +pub const ITER_GROUP: iter_mode = 2; +pub const ITER_STREAM: iter_mode = 1; +pub const ITER_INDEX: iter_mode = 0; +pub const ITER_METHOD_LEFTMOST: iter_method = 2; +pub const ITER_METHOD_NEXT: iter_method = 1; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct index_cat_info { + pub uncompressed_size: lzma_vli, + pub file_size: lzma_vli, + pub block_number_add: lzma_vli, + pub stream_number_add: u32, + pub streams: *mut index_tree, +} +pub type iter_mode = c_uint; +pub type iter_method = c_uint; +#[inline] +extern "C" fn bsr32(n: u32) -> u32 { + n.leading_zeros() as i32 as u32 ^ 31 +} +#[inline] +extern "C" fn ctz32(n: u32) -> u32 { + n.trailing_zeros() as i32 as u32 +} +pub const INDEX_GROUP_SIZE: u32 = 512; +pub const PREALLOC_MAX: usize = (SIZE_MAX as usize) + .wrapping_sub(core::mem::size_of::()) + .wrapping_div(core::mem::size_of::()); +unsafe fn index_tree_init(tree: *mut index_tree) { + (*tree).root = core::ptr::null_mut(); + (*tree).leftmost = core::ptr::null_mut(); + (*tree).rightmost = core::ptr::null_mut(); + (*tree).count = 0; +} +unsafe fn index_tree_node_end( + node: *mut index_tree_node, + allocator: *const lzma_allocator, + free_func: Option ()>, +) { + if !(*node).left.is_null() { + index_tree_node_end((*node).left, allocator, free_func); + } + if !(*node).right.is_null() { + index_tree_node_end((*node).right, allocator, free_func); + } + free_func.unwrap()(node as *mut c_void, allocator); +} +unsafe fn index_tree_end( + tree: *mut index_tree, + allocator: *const lzma_allocator, + free_func: Option ()>, +) { + if !(*tree).root.is_null() { + index_tree_node_end((*tree).root, allocator, free_func); + } +} +unsafe fn index_tree_append(tree: *mut index_tree, mut node: *mut index_tree_node) { + (*node).parent = (*tree).rightmost; + (*node).left = core::ptr::null_mut(); + (*node).right = core::ptr::null_mut(); + (*tree).count += 1; + if (*tree).root.is_null() { + (*tree).root = node; + (*tree).leftmost = node; + (*tree).rightmost = node; + return; + } + (*(*tree).rightmost).right = node; + (*tree).rightmost = node; + let mut up: u32 = (*tree).count ^ 1 << bsr32((*tree).count); + if up != 0 { + up = ctz32((*tree).count) + 2; + loop { + node = (*node).parent; + up -= 1; + if up == 0 { + break; + } + } + let pivot: *mut index_tree_node = (*node).right; + if (*node).parent.is_null() { + (*tree).root = pivot; + } else { + (*(*node).parent).right = pivot; + } + (*pivot).parent = (*node).parent; + (*node).right = (*pivot).left; + if !(*node).right.is_null() { + (*(*node).right).parent = node; + } + (*pivot).left = node; + (*node).parent = pivot; + } +} +unsafe fn index_tree_next(mut node: *const index_tree_node) -> *mut c_void { + if !(*node).right.is_null() { + node = (*node).right; + while !(*node).left.is_null() { + node = (*node).left; + } + return node as *mut c_void; + } + while !(*node).parent.is_null() && (*(*node).parent).right == node as *mut index_tree_node { + node = (*node).parent; + } + (*node).parent as *mut c_void +} +unsafe fn index_tree_locate(tree: *const index_tree, target: lzma_vli) -> *mut c_void { + let mut result: *const index_tree_node = core::ptr::null(); + let mut node: *const index_tree_node = (*tree).root; + while !node.is_null() { + if (*node).uncompressed_base > target { + node = (*node).left; + } else { + result = node; + node = (*node).right; + } + } + result as *mut c_void +} +unsafe fn index_stream_init( + compressed_base: lzma_vli, + uncompressed_base: lzma_vli, + stream_number: u32, + block_number_base: lzma_vli, + allocator: *const lzma_allocator, +) -> *mut index_stream { + let s: *mut index_stream = + lzma_alloc(core::mem::size_of::(), allocator) as *mut index_stream; + if s.is_null() { + return core::ptr::null_mut(); + } + (*s).node.uncompressed_base = uncompressed_base; + (*s).node.compressed_base = compressed_base; + (*s).node.parent = core::ptr::null_mut(); + (*s).node.left = core::ptr::null_mut(); + (*s).node.right = core::ptr::null_mut(); + (*s).number = stream_number; + (*s).block_number_base = block_number_base; + index_tree_init(::core::ptr::addr_of_mut!((*s).groups)); + (*s).record_count = 0; + (*s).index_list_size = 0; + (*s).stream_flags.version = UINT32_MAX; + (*s).stream_padding = 0; + s +} +unsafe extern "C" fn index_stream_end(node: *mut c_void, allocator: *const lzma_allocator) { + let s: *mut index_stream = node as *mut index_stream; + index_tree_end( + ::core::ptr::addr_of_mut!((*s).groups), + allocator, + Some(lzma_free as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> ()), + ); + lzma_free(s as *mut c_void, allocator); +} +unsafe fn index_init_plain(allocator: *const lzma_allocator) -> *mut lzma_index { + let i: *mut lzma_index = + lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_index; + if !i.is_null() { + index_tree_init(::core::ptr::addr_of_mut!((*i).streams)); + (*i).uncompressed_size = 0; + (*i).total_size = 0; + (*i).record_count = 0; + (*i).index_list_size = 0; + (*i).prealloc = INDEX_GROUP_SIZE as size_t; + (*i).checks = 0; + } + i +} +pub unsafe fn lzma_index_init(allocator: *const lzma_allocator) -> *mut lzma_index { + let i: *mut lzma_index = index_init_plain(allocator); + if i.is_null() { + return core::ptr::null_mut(); + } + let s: *mut index_stream = index_stream_init(0, 0, 1, 0, allocator); + if s.is_null() { + lzma_free(i as *mut c_void, allocator); + return core::ptr::null_mut(); + } + index_tree_append( + ::core::ptr::addr_of_mut!((*i).streams), + ::core::ptr::addr_of_mut!((*s).node), + ); + i +} +pub unsafe fn lzma_index_end(i: *mut lzma_index, allocator: *const lzma_allocator) { + if !i.is_null() { + index_tree_end( + ::core::ptr::addr_of_mut!((*i).streams), + allocator, + Some( + index_stream_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ), + ); + lzma_free(i as *mut c_void, allocator); + } +} +pub unsafe fn lzma_index_prealloc(i: *mut lzma_index, mut records: lzma_vli) { + if records > PREALLOC_MAX as lzma_vli { + records = PREALLOC_MAX as lzma_vli; + } + (*i).prealloc = records as size_t; +} +pub fn lzma_index_memusage(streams: lzma_vli, blocks: lzma_vli) -> u64 { + let alloc_overhead: size_t = (4_usize).wrapping_mul(core::mem::size_of::<*mut c_void>()); + let stream_base: size_t = (core::mem::size_of::()) + .wrapping_add(core::mem::size_of::()) + .wrapping_add((2_usize).wrapping_mul(alloc_overhead)); + let group_base: size_t = (core::mem::size_of::()) + .wrapping_add( + (INDEX_GROUP_SIZE as size_t).wrapping_mul(core::mem::size_of::()), + ) + .wrapping_add(alloc_overhead); + let groups: lzma_vli = blocks + .wrapping_add(INDEX_GROUP_SIZE as lzma_vli) + .wrapping_sub(1) + .wrapping_div(INDEX_GROUP_SIZE as lzma_vli); + let streams_mem: u64 = (streams as u64).wrapping_mul(stream_base as u64); + let groups_mem: u64 = (groups as u64).wrapping_mul(group_base as u64); + let index_base: u64 = + (core::mem::size_of::()).wrapping_add(alloc_overhead as usize) as u64; + let limit: u64 = (UINT64_MAX).wrapping_sub(index_base); + if streams == 0 + || streams > UINT32_MAX as lzma_vli + || blocks > LZMA_VLI_MAX + || streams > limit.wrapping_div(stream_base as u64) + || groups > limit.wrapping_div(group_base as u64) + || limit.wrapping_sub(streams_mem) < groups_mem + { + return UINT64_MAX; + } + index_base + .wrapping_add(streams_mem) + .wrapping_add(groups_mem) +} +pub fn lzma_index_memused(i: *const lzma_index) -> u64 { + unsafe { lzma_index_memusage((*i).streams.count as lzma_vli, (*i).record_count) } +} +pub fn lzma_index_block_count(i: *const lzma_index) -> lzma_vli { + unsafe { (*i).record_count } +} +pub fn lzma_index_stream_count(i: *const lzma_index) -> lzma_vli { + unsafe { (*i).streams.count as lzma_vli } +} +pub fn lzma_index_size(i: *const lzma_index) -> lzma_vli { + unsafe { index_size((*i).record_count, (*i).index_list_size) } +} +pub fn lzma_index_total_size(i: *const lzma_index) -> lzma_vli { + unsafe { (*i).total_size } +} +pub fn lzma_index_stream_size(i: *const lzma_index) -> lzma_vli { + unsafe { + (LZMA_STREAM_HEADER_SIZE as lzma_vli) + + (*i).total_size + + index_size((*i).record_count, (*i).index_list_size) + + LZMA_STREAM_HEADER_SIZE as lzma_vli + } +} +unsafe fn index_file_size( + compressed_base: lzma_vli, + unpadded_sum: lzma_vli, + record_count: lzma_vli, + index_list_size: lzma_vli, + stream_padding: lzma_vli, +) -> lzma_vli { + let mut file_size: lzma_vli = compressed_base + .wrapping_add((2 * LZMA_STREAM_HEADER_SIZE) as lzma_vli) + .wrapping_add(stream_padding) + .wrapping_add(vli_ceil4(unpadded_sum)); + if file_size > LZMA_VLI_MAX { + return LZMA_VLI_UNKNOWN; + } + file_size = file_size.wrapping_add(index_size(record_count, index_list_size)); + if file_size > LZMA_VLI_MAX { + return LZMA_VLI_UNKNOWN; + } + file_size +} +pub unsafe fn lzma_index_file_size(i: *const lzma_index) -> lzma_vli { + let s: *const index_stream = (*i).streams.rightmost as *const index_stream; + let g: *const index_group = (*s).groups.rightmost as *const index_group; + index_file_size( + (*s).node.compressed_base, + if g.is_null() { + 0 + } else { + (*(::core::ptr::addr_of!((*g).records) as *const index_record) + .offset((*g).last as isize)) + .unpadded_sum + }, + (*s).record_count, + (*s).index_list_size, + (*s).stream_padding, + ) +} +pub unsafe fn lzma_index_uncompressed_size(i: *const lzma_index) -> lzma_vli { + (*i).uncompressed_size +} +pub unsafe fn lzma_index_checks(i: *const lzma_index) -> u32 { + let mut checks: u32 = (*i).checks; + let s: *const index_stream = (*i).streams.rightmost as *const index_stream; + if (*s).stream_flags.version != UINT32_MAX { + checks = (checks | 1u32 << (*s).stream_flags.check) as u32; + } + checks +} +pub unsafe fn lzma_index_padding_size(i: *const lzma_index) -> u32 { + ((4_u64).wrapping_sub(index_size_unpadded((*i).record_count, (*i).index_list_size)) & 3) as u32 +} +pub unsafe fn lzma_index_stream_flags( + i: *mut lzma_index, + stream_flags: *const lzma_stream_flags, +) -> lzma_ret { + if i.is_null() || stream_flags.is_null() { + return LZMA_PROG_ERROR; + } + let ret_: lzma_ret = lzma_stream_flags_compare(stream_flags, stream_flags); + if ret_ != LZMA_OK { + return ret_; + } + let s: *mut index_stream = (*i).streams.rightmost as *mut index_stream; + (*s).stream_flags = *stream_flags; + LZMA_OK +} +pub unsafe fn lzma_index_stream_padding(i: *mut lzma_index, stream_padding: lzma_vli) -> lzma_ret { + if i.is_null() || stream_padding > LZMA_VLI_MAX || stream_padding & 3 != 0 { + return LZMA_PROG_ERROR; + } + let s: *mut index_stream = (*i).streams.rightmost as *mut index_stream; + let old_stream_padding: lzma_vli = (*s).stream_padding; + (*s).stream_padding = 0; + if lzma_index_file_size(i).wrapping_add(stream_padding) > LZMA_VLI_MAX { + (*s).stream_padding = old_stream_padding; + return LZMA_DATA_ERROR; + } + (*s).stream_padding = stream_padding; + LZMA_OK +} +pub unsafe fn lzma_index_append( + i: *mut lzma_index, + allocator: *const lzma_allocator, + unpadded_size: lzma_vli, + uncompressed_size: lzma_vli, +) -> lzma_ret { + if i.is_null() + || unpadded_size < UNPADDED_SIZE_MIN + || unpadded_size > UNPADDED_SIZE_MAX + || uncompressed_size > LZMA_VLI_MAX + { + return LZMA_PROG_ERROR; + } + let s: *mut index_stream = (*i).streams.rightmost as *mut index_stream; + let mut g: *mut index_group = (*s).groups.rightmost as *mut index_group; + let compressed_base: lzma_vli = if g.is_null() { + 0 + } else { + vli_ceil4( + (*(::core::ptr::addr_of_mut!((*g).records) as *mut index_record) + .offset((*g).last as isize)) + .unpadded_sum, + ) as lzma_vli + }; + let uncompressed_base: lzma_vli = if g.is_null() { + 0 + } else { + (*(::core::ptr::addr_of_mut!((*g).records) as *mut index_record).offset((*g).last as isize)) + .uncompressed_sum + }; + let index_list_size_add: u32 = + lzma_vli_size(unpadded_size) as u32 + lzma_vli_size(uncompressed_size) as u32; + if uncompressed_base.wrapping_add(uncompressed_size) > LZMA_VLI_MAX { + return LZMA_DATA_ERROR; + } + if compressed_base.wrapping_add(unpadded_size) > UNPADDED_SIZE_MAX { + return LZMA_DATA_ERROR; + } + if index_file_size( + (*s).node.compressed_base, + compressed_base.wrapping_add(unpadded_size), + (*s).record_count.wrapping_add(1), + (*s).index_list_size + .wrapping_add(index_list_size_add as lzma_vli), + (*s).stream_padding, + ) == LZMA_VLI_UNKNOWN + { + return LZMA_DATA_ERROR; + } + if index_size( + (*i).record_count.wrapping_add(1), + (*i).index_list_size + .wrapping_add(index_list_size_add as lzma_vli), + ) > LZMA_BACKWARD_SIZE_MAX + { + return LZMA_DATA_ERROR; + } + if !g.is_null() && (*g).last + 1 < (*g).allocated { + (*g).last += 1; + } else { + g = lzma_alloc( + core::mem::size_of::() + + (*i).prealloc * core::mem::size_of::(), + allocator, + ) as *mut index_group; + if g.is_null() { + return LZMA_MEM_ERROR; + } + (*g).last = 0; + (*g).allocated = (*i).prealloc; + (*i).prealloc = INDEX_GROUP_SIZE as size_t; + (*g).node.uncompressed_base = uncompressed_base; + (*g).node.compressed_base = compressed_base; + (*g).number_base = (*s).record_count + 1; + index_tree_append( + ::core::ptr::addr_of_mut!((*s).groups), + ::core::ptr::addr_of_mut!((*g).node), + ); + } + (*(::core::ptr::addr_of_mut!((*g).records) as *mut index_record).offset((*g).last as isize)) + .uncompressed_sum = uncompressed_base + uncompressed_size; + (*(::core::ptr::addr_of_mut!((*g).records) as *mut index_record).offset((*g).last as isize)) + .unpadded_sum = compressed_base + unpadded_size; + (*s).record_count += 1; + (*s).index_list_size += index_list_size_add as lzma_vli; + (*i).total_size += vli_ceil4(unpadded_size); + (*i).uncompressed_size += uncompressed_size; + (*i).record_count += 1; + (*i).index_list_size += index_list_size_add as lzma_vli; + LZMA_OK +} +unsafe fn index_cat_helper(info: *const index_cat_info, this: *mut index_stream) { + let left: *mut index_stream = (*this).node.left as *mut index_stream; + let right: *mut index_stream = (*this).node.right as *mut index_stream; + if !left.is_null() { + index_cat_helper(info, left); + } + (*this).node.uncompressed_base += (*info).uncompressed_size; + (*this).node.compressed_base += (*info).file_size; + (*this).number += (*info).stream_number_add; + (*this).block_number_base += (*info).block_number_add; + index_tree_append((*info).streams, ::core::ptr::addr_of_mut!((*this).node)); + if !right.is_null() { + index_cat_helper(info, right); + } +} +pub unsafe fn lzma_index_cat( + dest: *mut lzma_index, + src: *mut lzma_index, + allocator: *const lzma_allocator, +) -> lzma_ret { + if dest.is_null() || src.is_null() { + return LZMA_PROG_ERROR; + } + let dest_file_size: lzma_vli = lzma_index_file_size(dest); + if dest_file_size.wrapping_add(lzma_index_file_size(src)) > LZMA_VLI_MAX + || (*dest) + .uncompressed_size + .wrapping_add((*src).uncompressed_size) + > LZMA_VLI_MAX + { + return LZMA_DATA_ERROR; + } + let dest_size: lzma_vli = + index_size_unpadded((*dest).record_count, (*dest).index_list_size) as lzma_vli; + let src_size: lzma_vli = + index_size_unpadded((*src).record_count, (*src).index_list_size) as lzma_vli; + if vli_ceil4(dest_size.wrapping_add(src_size)) > LZMA_BACKWARD_SIZE_MAX { + return LZMA_DATA_ERROR; + } + let s: *mut index_stream = (*dest).streams.rightmost as *mut index_stream; + let g: *mut index_group = (*s).groups.rightmost as *mut index_group; + if !g.is_null() && (*g).last + 1 < (*g).allocated { + let newg: *mut index_group = lzma_alloc( + core::mem::size_of::() + + ((*g).last + 1) * core::mem::size_of::(), + allocator, + ) as *mut index_group; + if newg.is_null() { + return LZMA_MEM_ERROR; + } + (*newg).node = (*g).node; + (*newg).allocated = (*g).last + 1; + (*newg).last = (*g).last; + (*newg).number_base = (*g).number_base; + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!((*g).records) as *const u8, + ::core::ptr::addr_of_mut!((*newg).records) as *mut u8, + (*newg).allocated * core::mem::size_of::(), + ); + if !(*g).node.parent.is_null() { + (*(*g).node.parent).right = ::core::ptr::addr_of_mut!((*newg).node); + } + if (*s).groups.leftmost == ::core::ptr::addr_of_mut!((*g).node) { + (*s).groups.leftmost = ::core::ptr::addr_of_mut!((*newg).node); + (*s).groups.root = ::core::ptr::addr_of_mut!((*newg).node); + } + (*s).groups.rightmost = ::core::ptr::addr_of_mut!((*newg).node); + lzma_free(g as *mut c_void, allocator); + } + (*dest).checks = lzma_index_checks(dest); + let info: index_cat_info = index_cat_info { + uncompressed_size: (*dest).uncompressed_size, + file_size: dest_file_size, + block_number_add: (*dest).record_count, + stream_number_add: (*dest).streams.count, + streams: ::core::ptr::addr_of_mut!((*dest).streams), + }; + index_cat_helper( + ::core::ptr::addr_of!(info), + (*src).streams.root as *mut index_stream, + ); + (*dest).uncompressed_size += (*src).uncompressed_size; + (*dest).total_size += (*src).total_size; + (*dest).record_count += (*src).record_count; + (*dest).index_list_size += (*src).index_list_size; + (*dest).checks |= (*src).checks; + lzma_free(src as *mut c_void, allocator); + LZMA_OK +} +unsafe fn index_dup_stream( + src: *const index_stream, + allocator: *const lzma_allocator, +) -> *mut index_stream { + if (*src).record_count > PREALLOC_MAX as lzma_vli { + return core::ptr::null_mut(); + } + let dest: *mut index_stream = index_stream_init( + (*src).node.compressed_base, + (*src).node.uncompressed_base, + (*src).number, + (*src).block_number_base, + allocator, + ); + if dest.is_null() { + return core::ptr::null_mut(); + } + (*dest).record_count = (*src).record_count; + (*dest).index_list_size = (*src).index_list_size; + (*dest).stream_flags = (*src).stream_flags; + (*dest).stream_padding = (*src).stream_padding; + if (*src).groups.leftmost.is_null() { + return dest; + } + let destg: *mut index_group = lzma_alloc( + (core::mem::size_of::() as lzma_vli + + (*src).record_count * core::mem::size_of::() as lzma_vli) + as size_t, + allocator, + ) as *mut index_group; + if destg.is_null() { + index_stream_end(dest as *mut c_void, allocator); + return core::ptr::null_mut(); + } + (*destg).node.uncompressed_base = 0; + (*destg).node.compressed_base = 0; + (*destg).number_base = 1; + (*destg).allocated = (*src).record_count as size_t; + (*destg).last = ((*src).record_count - 1) as size_t; + let mut srcg: *const index_group = (*src).groups.leftmost as *const index_group; + let mut i: size_t = 0; + loop { + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of!((*srcg).records) as *const u8, + (::core::ptr::addr_of_mut!((*destg).records) as *mut index_record).offset(i as isize) + as *mut u8, + ((*srcg).last + 1) * core::mem::size_of::(), + ); + i += (*srcg).last + 1; + srcg = index_tree_next(::core::ptr::addr_of!((*srcg).node)) as *const index_group; + if srcg.is_null() { + break; + } + } + index_tree_append( + ::core::ptr::addr_of_mut!((*dest).groups), + ::core::ptr::addr_of_mut!((*destg).node), + ); + dest +} +pub unsafe fn lzma_index_dup( + src: *const lzma_index, + allocator: *const lzma_allocator, +) -> *mut lzma_index { + let dest: *mut lzma_index = index_init_plain(allocator); + if dest.is_null() { + return core::ptr::null_mut(); + } + (*dest).uncompressed_size = (*src).uncompressed_size; + (*dest).total_size = (*src).total_size; + (*dest).record_count = (*src).record_count; + (*dest).index_list_size = (*src).index_list_size; + let mut srcstream: *const index_stream = (*src).streams.leftmost as *const index_stream; + loop { + let deststream: *mut index_stream = index_dup_stream(srcstream, allocator); + if deststream.is_null() { + lzma_index_end(dest, allocator); + return core::ptr::null_mut(); + } + index_tree_append( + ::core::ptr::addr_of_mut!((*dest).streams), + ::core::ptr::addr_of_mut!((*deststream).node), + ); + srcstream = + index_tree_next(::core::ptr::addr_of!((*srcstream).node)) as *const index_stream; + if srcstream.is_null() { + break; + } + } + dest +} +unsafe fn iter_set_info(iter: *mut lzma_index_iter) { + let i: *const lzma_index = (*iter).internal[ITER_INDEX as usize].p as *const lzma_index; + let stream: *const index_stream = + (*iter).internal[ITER_STREAM as usize].p as *const index_stream; + let group: *const index_group = (*iter).internal[ITER_GROUP as usize].p as *const index_group; + let record: size_t = (*iter).internal[ITER_RECORD as usize].s; + if group.is_null() { + (*iter).internal[ITER_METHOD as usize].s = ITER_METHOD_LEFTMOST as size_t; + } else if (*i).streams.rightmost + != ::core::ptr::addr_of!((*stream).node) as *mut index_tree_node + || (*stream).groups.rightmost + != ::core::ptr::addr_of!((*group).node) as *mut index_tree_node + { + (*iter).internal[ITER_METHOD as usize].s = ITER_METHOD_NORMAL as size_t; + } else if (*stream).groups.leftmost + != ::core::ptr::addr_of!((*group).node) as *mut index_tree_node + { + (*iter).internal[ITER_METHOD as usize].s = ITER_METHOD_NEXT as size_t; + (*iter).internal[ITER_GROUP as usize].p = (*group).node.parent as *const c_void; + } else { + (*iter).internal[ITER_METHOD as usize].s = ITER_METHOD_LEFTMOST as size_t; + (*iter).internal[ITER_GROUP as usize].p = core::ptr::null(); + } + (*iter).stream.number = (*stream).number as lzma_vli; + (*iter).stream.block_count = (*stream).record_count; + (*iter).stream.compressed_offset = (*stream).node.compressed_base; + (*iter).stream.uncompressed_offset = (*stream).node.uncompressed_base; + (*iter).stream.flags = if (*stream).stream_flags.version == UINT32_MAX { + core::ptr::null() + } else { + ::core::ptr::addr_of!((*stream).stream_flags) + }; + (*iter).stream.padding = (*stream).stream_padding; + if (*stream).groups.rightmost.is_null() { + (*iter).stream.compressed_size = + index_size(0, 0) + (2 * LZMA_STREAM_HEADER_SIZE) as lzma_vli; + (*iter).stream.uncompressed_size = 0; + } else { + let g: *const index_group = (*stream).groups.rightmost as *const index_group; + (*iter).stream.compressed_size = (2 * LZMA_STREAM_HEADER_SIZE) as lzma_vli + + index_size((*stream).record_count, (*stream).index_list_size) + + vli_ceil4( + (*(::core::ptr::addr_of!((*g).records) as *const index_record) + .offset((*g).last as isize)) + .unpadded_sum, + ); + (*iter).stream.uncompressed_size = (*(::core::ptr::addr_of!((*g).records) + as *const index_record) + .offset((*g).last as isize)) + .uncompressed_sum; + } + if !group.is_null() { + (*iter).block.number_in_stream = (*group).number_base + record as lzma_vli; + (*iter).block.number_in_file = (*iter).block.number_in_stream + (*stream).block_number_base; + (*iter).block.compressed_stream_offset = if record == 0 { + (*group).node.compressed_base + } else { + vli_ceil4( + (*(::core::ptr::addr_of!((*group).records) as *const index_record) + .offset((record - 1) as isize)) + .unpadded_sum, + ) + }; + (*iter).block.uncompressed_stream_offset = if record == 0 { + (*group).node.uncompressed_base + } else { + (*(::core::ptr::addr_of!((*group).records) as *const index_record) + .offset((record - 1) as isize)) + .uncompressed_sum + }; + (*iter).block.uncompressed_size = (*(::core::ptr::addr_of!((*group).records) + as *const index_record) + .offset(record as isize)) + .uncompressed_sum + - (*iter).block.uncompressed_stream_offset; + (*iter).block.unpadded_size = (*(::core::ptr::addr_of!((*group).records) + as *const index_record) + .offset(record as isize)) + .unpadded_sum + - (*iter).block.compressed_stream_offset; + (*iter).block.total_size = vli_ceil4((*iter).block.unpadded_size); + (*iter).block.compressed_stream_offset += LZMA_STREAM_HEADER_SIZE as lzma_vli; + (*iter).block.compressed_file_offset = + (*iter).block.compressed_stream_offset + (*iter).stream.compressed_offset; + (*iter).block.uncompressed_file_offset = + (*iter).block.uncompressed_stream_offset + (*iter).stream.uncompressed_offset; + } +} +pub unsafe fn lzma_index_iter_init(iter: *mut lzma_index_iter, i: *const lzma_index) { + (*iter).internal[ITER_INDEX as usize].p = i as *const c_void; + lzma_index_iter_rewind(iter); +} +pub unsafe fn lzma_index_iter_rewind(iter: *mut lzma_index_iter) { + (*iter).internal[ITER_STREAM as usize].p = core::ptr::null(); + (*iter).internal[ITER_GROUP as usize].p = core::ptr::null(); + (*iter).internal[ITER_RECORD as usize].s = 0; + (*iter).internal[ITER_METHOD as usize].s = ITER_METHOD_NORMAL as size_t; +} +pub unsafe fn lzma_index_iter_next( + iter: *mut lzma_index_iter, + mode: lzma_index_iter_mode, +) -> lzma_bool { + if mode > LZMA_INDEX_ITER_NONEMPTY_BLOCK { + return true as lzma_bool; + } + let i: *const lzma_index = (*iter).internal[ITER_INDEX as usize].p as *const lzma_index; + let mut stream: *const index_stream = + (*iter).internal[ITER_STREAM as usize].p as *const index_stream; + let mut group: *const index_group = core::ptr::null(); + let mut record: size_t = (*iter).internal[ITER_RECORD as usize].s; + if mode != LZMA_INDEX_ITER_STREAM { + match (*iter).internal[ITER_METHOD as usize].s { + 0 => { + group = (*iter).internal[ITER_GROUP as usize].p as *const index_group; + } + 1 => { + group = index_tree_next( + (*iter).internal[ITER_GROUP as usize].p as *const index_tree_node, + ) as *const index_group; + } + 2 => { + group = (*stream).groups.leftmost as *const index_group; + } + _ => {} + } + } + loop { + if stream.is_null() { + stream = (*i).streams.leftmost as *const index_stream; + if mode >= LZMA_INDEX_ITER_BLOCK { + while (*stream).groups.leftmost.is_null() { + stream = index_tree_next(::core::ptr::addr_of!((*stream).node)) + as *const index_stream; + if stream.is_null() { + return true as lzma_bool; + } + } + } + group = (*stream).groups.leftmost as *const index_group; + record = 0; + } else if !group.is_null() && record < (*group).last { + record += 1; + } else { + record = 0; + if !group.is_null() { + group = index_tree_next(::core::ptr::addr_of!((*group).node)) as *const index_group; + } + if group.is_null() { + loop { + stream = index_tree_next(::core::ptr::addr_of!((*stream).node)) + as *const index_stream; + if stream.is_null() { + return true as lzma_bool; + } + if mode < LZMA_INDEX_ITER_BLOCK || !(*stream).groups.leftmost.is_null() { + break; + } + } + group = (*stream).groups.leftmost as *const index_group; + } + } + if mode != LZMA_INDEX_ITER_NONEMPTY_BLOCK { + break; + } + if record == 0 { + if (*group).node.uncompressed_base + != (*(::core::ptr::addr_of!((*group).records) as *const index_record)) + .uncompressed_sum + { + break; + } + } else if (*(::core::ptr::addr_of!((*group).records) as *const index_record) + .offset((record - 1) as isize)) + .uncompressed_sum + != (*(::core::ptr::addr_of!((*group).records) as *const index_record) + .offset(record as isize)) + .uncompressed_sum + { + break; + } + } + (*iter).internal[ITER_STREAM as usize].p = stream as *const c_void; + (*iter).internal[ITER_GROUP as usize].p = group as *const c_void; + (*iter).internal[ITER_RECORD as usize].s = record; + iter_set_info(iter); + false as lzma_bool +} +pub unsafe fn lzma_index_iter_locate( + iter: *mut lzma_index_iter, + mut target: lzma_vli, +) -> lzma_bool { + let i: *const lzma_index = (*iter).internal[ITER_INDEX as usize].p as *const lzma_index; + if (*i).uncompressed_size <= target { + return true as lzma_bool; + } + let stream: *const index_stream = + index_tree_locate(::core::ptr::addr_of!((*i).streams), target) as *const index_stream; + target -= (*stream).node.uncompressed_base; + let group: *const index_group = + index_tree_locate(::core::ptr::addr_of!((*stream).groups), target) as *const index_group; + let mut left: size_t = 0; + let mut right: size_t = (*group).last; + while left < right { + let pos: size_t = left + (right - left) / 2; + if (*(::core::ptr::addr_of!((*group).records) as *const index_record).offset(pos as isize)) + .uncompressed_sum + <= target + { + left = pos + 1; + } else { + right = pos; + } + } + (*iter).internal[ITER_STREAM as usize].p = stream as *const c_void; + (*iter).internal[ITER_GROUP as usize].p = group as *const c_void; + (*iter).internal[ITER_RECORD as usize].s = left; + iter_set_info(iter); + false as lzma_bool +} diff --git a/liblzma-rs/src/common/index_decoder.rs b/liblzma-rs/src/common/index_decoder.rs new file mode 100644 index 00000000..99950371 --- /dev/null +++ b/liblzma-rs/src/common/index_decoder.rs @@ -0,0 +1,392 @@ +use crate::common::index::lzma_index_prealloc; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_coder { + pub sequence: index_decoder_seq, + pub memlimit: u64, + pub index: *mut lzma_index, + pub index_ptr: *mut *mut lzma_index, + pub count: lzma_vli, + pub unpadded_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub pos: size_t, + pub crc32: u32, +} +pub type index_decoder_seq = c_uint; +pub const SEQ_CRC32: index_decoder_seq = 7; +pub const SEQ_PADDING: index_decoder_seq = 6; +pub const SEQ_PADDING_INIT: index_decoder_seq = 5; +pub const SEQ_UNCOMPRESSED: index_decoder_seq = 4; +pub const SEQ_UNPADDED: index_decoder_seq = 3; +pub const SEQ_MEMUSAGE: index_decoder_seq = 2; +pub const SEQ_COUNT: index_decoder_seq = 1; +pub const SEQ_INDICATOR: index_decoder_seq = 0; +unsafe extern "C" fn index_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + _out: *mut u8, + _out_pos: *mut size_t, + _out_size: size_t, + _action: lzma_action, +) -> lzma_ret { + let mut current_block: u64; + let coder: *mut lzma_index_coder = coder_ptr as *mut lzma_index_coder; + let in_start: size_t = *in_pos; + let mut ret: lzma_ret = LZMA_OK; + while *in_pos < in_size { + match (*coder).sequence { + 0 => { + let byte = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if byte != INDEX_INDICATOR { + return LZMA_DATA_ERROR; + } + (*coder).sequence = SEQ_COUNT; + continue; + } + 1 => { + ret = lzma_vli_decode( + ::core::ptr::addr_of_mut!((*coder).count), + ::core::ptr::addr_of_mut!((*coder).pos), + in_0, + in_pos, + in_size, + ); + if ret != LZMA_STREAM_END { + break; + } + (*coder).pos = 0; + (*coder).sequence = SEQ_MEMUSAGE; + current_block = 7642845755631126846; + } + 2 => { + current_block = 7642845755631126846; + } + 3 | 4 => { + let size: *mut lzma_vli = if (*coder).sequence == SEQ_UNPADDED { + ::core::ptr::addr_of_mut!((*coder).unpadded_size) + } else { + ::core::ptr::addr_of_mut!((*coder).uncompressed_size) + }; + ret = lzma_vli_decode( + size, + ::core::ptr::addr_of_mut!((*coder).pos), + in_0, + in_pos, + in_size, + ); + if ret != LZMA_STREAM_END { + break; + } + ret = LZMA_OK; + (*coder).pos = 0; + if (*coder).sequence == SEQ_UNPADDED { + if (*coder).unpadded_size < UNPADDED_SIZE_MIN + || (*coder).unpadded_size > UNPADDED_SIZE_MAX + { + return LZMA_DATA_ERROR; + } + (*coder).sequence = SEQ_UNCOMPRESSED; + } else { + let ret_: lzma_ret = lzma_index_append( + (*coder).index, + allocator, + (*coder).unpadded_size, + (*coder).uncompressed_size, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).count -= 1; + (*coder).sequence = (if (*coder).count == 0 { + SEQ_PADDING_INIT + } else { + SEQ_UNPADDED + }) as index_decoder_seq; + } + continue; + } + 5 => { + (*coder).pos = lzma_index_padding_size((*coder).index) as size_t; + (*coder).sequence = SEQ_PADDING; + current_block = 8340016495055110192; + } + 6 => { + current_block = 8340016495055110192; + } + 7 => { + current_block = 9471676622948044094; + } + _ => return LZMA_PROG_ERROR, + } + match current_block { + 8340016495055110192 => { + if (*coder).pos > 0 { + (*coder).pos -= 1; + let byte = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if byte != 0 { + return LZMA_DATA_ERROR; + } + continue; + } else { + (*coder).crc32 = lzma_crc32( + in_0.offset(in_start as isize), + *in_pos - in_start, + (*coder).crc32, + ); + (*coder).sequence = SEQ_CRC32; + } + } + 7642845755631126846 => { + if lzma_index_memusage(1, (*coder).count) > (*coder).memlimit { + ret = LZMA_MEMLIMIT_ERROR; + break; + } else { + lzma_index_prealloc((*coder).index, (*coder).count); + ret = LZMA_OK; + (*coder).sequence = (if (*coder).count == 0 { + SEQ_PADDING_INIT + } else { + SEQ_UNPADDED + }) as index_decoder_seq; + continue; + } + } + _ => {} + } + loop { + if *in_pos == in_size { + return LZMA_OK; + } + let val = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if (*coder).crc32 >> ((*coder).pos * 8) & 0xff != val as u32 { + return LZMA_DATA_ERROR; + } + (*coder).pos += 1; + if (*coder).pos >= 4 { + break; + } + } + *(*coder).index_ptr = (*coder).index; + (*coder).index = core::ptr::null_mut(); + return LZMA_STREAM_END; + } + let in_used: size_t = *in_pos - in_start; + if in_used > 0 { + (*coder).crc32 = lzma_crc32(in_0.offset(in_start as isize), in_used, (*coder).crc32); + } + ret +} +unsafe extern "C" fn index_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_index_coder = coder_ptr as *mut lzma_index_coder; + lzma_index_end((*coder).index, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn index_decoder_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_index_coder = coder_ptr as *mut lzma_index_coder; + *memusage = lzma_index_memusage(1, (*coder).count); + *old_memlimit = (*coder).memlimit; + if new_memlimit != 0 { + if new_memlimit < *memusage { + return LZMA_MEMLIMIT_ERROR; + } + (*coder).memlimit = new_memlimit; + } + LZMA_OK +} +unsafe fn index_decoder_reset( + coder: *mut lzma_index_coder, + allocator: *const lzma_allocator, + i: *mut *mut lzma_index, + memlimit: u64, +) -> lzma_ret { + (*coder).index_ptr = i; + *i = core::ptr::null_mut(); + (*coder).index = lzma_index_init(allocator); + if (*coder).index.is_null() { + return LZMA_MEM_ERROR; + } + (*coder).sequence = SEQ_INDICATOR; + (*coder).memlimit = if 1 > memlimit { 1 } else { memlimit }; + (*coder).count = 0; + (*coder).pos = 0; + (*coder).crc32 = 0; + LZMA_OK +} +pub unsafe extern "C" fn lzma_index_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + i: *mut *mut lzma_index, + memlimit: u64, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut *mut lzma_index, + u64, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_index_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut *mut lzma_index, + u64, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut *mut lzma_index, + u64, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_index_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *mut *mut lzma_index, + u64, + ) -> lzma_ret, + )); + if i.is_null() { + return LZMA_PROG_ERROR; + } + let mut coder: *mut lzma_index_coder = (*next).coder as *mut lzma_index_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + index_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + index_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).memconfig = Some( + index_decoder_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*coder).index = core::ptr::null_mut(); + } else { + lzma_index_end((*coder).index, allocator); + } + index_decoder_reset(coder, allocator, i, memlimit) +} +pub unsafe fn lzma_index_decoder( + strm: *mut lzma_stream, + i: *mut *mut lzma_index, + memlimit: u64, +) -> lzma_ret { + if !i.is_null() { + *i = core::ptr::null_mut(); + } + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_index_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + i, + memlimit, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} +pub unsafe fn lzma_index_buffer_decode( + i: *mut *mut lzma_index, + memlimit: *mut u64, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + if !i.is_null() { + *i = core::ptr::null_mut(); + } + if i.is_null() || memlimit.is_null() || in_0.is_null() || in_pos.is_null() || *in_pos > in_size + { + return LZMA_PROG_ERROR; + } + let mut coder: lzma_index_coder = lzma_index_coder { + sequence: SEQ_INDICATOR, + memlimit: 0, + index: core::ptr::null_mut(), + index_ptr: core::ptr::null_mut(), + count: 0, + unpadded_size: 0, + uncompressed_size: 0, + pos: 0, + crc32: 0, + }; + let ret_: lzma_ret = + index_decoder_reset(::core::ptr::addr_of_mut!(coder), allocator, i, *memlimit); + if ret_ != LZMA_OK { + return ret_; + } + let in_start: size_t = *in_pos; + let mut ret: lzma_ret = index_decode( + ::core::ptr::addr_of_mut!(coder) as *mut c_void, + allocator, + in_0, + in_pos, + in_size, + core::ptr::null_mut(), + core::ptr::null_mut(), + 0, + LZMA_RUN, + ); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + } else { + lzma_index_end(coder.index, allocator); + *in_pos = in_start; + if ret == LZMA_OK { + ret = LZMA_DATA_ERROR; + } else if ret == LZMA_MEMLIMIT_ERROR { + *memlimit = lzma_index_memusage(1, coder.count); + } + } + ret +} diff --git a/liblzma-rs/src/common/index_encoder.rs b/liblzma-rs/src/common/index_encoder.rs new file mode 100644 index 00000000..e71ad6e2 --- /dev/null +++ b/liblzma-rs/src/common/index_encoder.rs @@ -0,0 +1,321 @@ +use crate::common::index::{lzma_index_block_count, lzma_index_iter_init, lzma_index_iter_next}; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_coder { + pub sequence: index_encoder_seq, + pub index: *const lzma_index, + pub iter: lzma_index_iter, + pub pos: size_t, + pub crc32: u32, +} +pub type index_encoder_seq = c_uint; +pub const SEQ_CRC32: index_encoder_seq = 6; +pub const SEQ_PADDING: index_encoder_seq = 5; +pub const SEQ_NEXT: index_encoder_seq = 4; +pub const SEQ_UNCOMPRESSED: index_encoder_seq = 3; +pub const SEQ_UNPADDED: index_encoder_seq = 2; +pub const SEQ_COUNT: index_encoder_seq = 1; +pub const SEQ_INDICATOR: index_encoder_seq = 0; +unsafe extern "C" fn index_encode( + coder_ptr: *mut c_void, + _allocator: *const lzma_allocator, + _in_0: *const u8, + _in_pos: *mut size_t, + _in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + _action: lzma_action, +) -> lzma_ret { + let mut current_block: u64; + let coder: *mut lzma_index_coder = coder_ptr as *mut lzma_index_coder; + let out_start: size_t = *out_pos; + let mut ret: lzma_ret = LZMA_OK; + while *out_pos < out_size { + match (*coder).sequence { + 0 => { + *out.offset(*out_pos as isize) = INDEX_INDICATOR; + *out_pos += 1; + (*coder).sequence = SEQ_COUNT; + continue; + } + 1 => { + let count: lzma_vli = lzma_index_block_count((*coder).index) as lzma_vli; + ret = lzma_vli_encode( + count, + ::core::ptr::addr_of_mut!((*coder).pos), + out, + out_pos, + out_size, + ); + if ret != LZMA_STREAM_END { + break; + } + ret = LZMA_OK; + (*coder).pos = 0; + (*coder).sequence = SEQ_NEXT; + continue; + } + 4 => { + if lzma_index_iter_next( + ::core::ptr::addr_of_mut!((*coder).iter), + LZMA_INDEX_ITER_BLOCK, + ) != 0 + { + (*coder).pos = lzma_index_padding_size((*coder).index) as size_t; + (*coder).sequence = SEQ_PADDING; + continue; + } else { + (*coder).sequence = SEQ_UNPADDED; + } + current_block = 10048703153582371463; + } + 2 | 3 => { + current_block = 10048703153582371463; + } + 5 => { + if (*coder).pos > 0 { + (*coder).pos -= 1; + *out.offset(*out_pos as isize) = 0; + *out_pos += 1; + continue; + } else { + (*coder).crc32 = lzma_crc32( + out.offset(out_start as isize), + *out_pos - out_start, + (*coder).crc32, + ); + (*coder).sequence = SEQ_CRC32; + } + current_block = 10175200006830010844; + } + 6 => { + current_block = 10175200006830010844; + } + _ => return LZMA_PROG_ERROR, + } + match current_block { + 10048703153582371463 => { + let size: lzma_vli = if (*coder).sequence == SEQ_UNPADDED { + (*coder).iter.block.unpadded_size + } else { + (*coder).iter.block.uncompressed_size + }; + ret = lzma_vli_encode( + size, + ::core::ptr::addr_of_mut!((*coder).pos), + out, + out_pos, + out_size, + ); + if ret != LZMA_STREAM_END { + break; + } + ret = LZMA_OK; + (*coder).pos = 0; + (*coder).sequence += 1; + } + _ => { + loop { + if *out_pos == out_size { + return LZMA_OK; + } + *out.offset(*out_pos as isize) = + ((*coder).crc32 >> ((*coder).pos * 8) & 0xff) as u8; + *out_pos += 1; + (*coder).pos += 1; + if (*coder).pos >= 4 { + break; + } + } + return LZMA_STREAM_END; + } + } + } + let out_used: size_t = *out_pos - out_start; + if out_used > 0 { + (*coder).crc32 = lzma_crc32(out.offset(out_start as isize), out_used, (*coder).crc32); + } + ret +} +unsafe extern "C" fn index_encoder_end(coder: *mut c_void, allocator: *const lzma_allocator) { + crate::alloc::internal_free(coder, allocator); +} +unsafe fn index_encoder_reset(coder: *mut lzma_index_coder, i: *const lzma_index) { + lzma_index_iter_init(::core::ptr::addr_of_mut!((*coder).iter), i); + (*coder).sequence = SEQ_INDICATOR; + (*coder).index = i; + (*coder).pos = 0; + (*coder).crc32 = 0; +} +pub unsafe extern "C" fn lzma_index_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + i: *const lzma_index, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_index, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_index_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_index, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_index, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_index_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_index, + ) -> lzma_ret, + )); + if i.is_null() { + return LZMA_PROG_ERROR; + } + if (*next).coder.is_null() { + (*next).coder = + crate::alloc::internal_alloc_object::(allocator) as *mut c_void; + if (*next).coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).code = Some( + index_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + index_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + } + index_encoder_reset((*next).coder as *mut lzma_index_coder, i); + LZMA_OK +} +pub unsafe fn lzma_index_encoder(strm: *mut lzma_stream, i: *const lzma_index) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_index_encoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + i, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} +pub unsafe fn lzma_index_buffer_encode( + i: *const lzma_index, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if i.is_null() || out.is_null() || out_pos.is_null() || *out_pos > out_size { + return LZMA_PROG_ERROR; + } + if ((out_size - *out_pos) as lzma_vli) < lzma_index_size(i) { + return LZMA_BUF_ERROR; + } + let mut coder: lzma_index_coder = lzma_index_coder { + sequence: SEQ_INDICATOR, + index: core::ptr::null(), + iter: lzma_index_iter { + stream: lzma_index_iter_stream { + flags: core::ptr::null(), + reserved_ptr1: core::ptr::null(), + reserved_ptr2: core::ptr::null(), + reserved_ptr3: core::ptr::null(), + number: 0, + block_count: 0, + compressed_offset: 0, + uncompressed_offset: 0, + compressed_size: 0, + uncompressed_size: 0, + padding: 0, + reserved_vli1: 0, + reserved_vli2: 0, + reserved_vli3: 0, + reserved_vli4: 0, + }, + block: lzma_index_iter_block { + number_in_file: 0, + compressed_file_offset: 0, + uncompressed_file_offset: 0, + number_in_stream: 0, + compressed_stream_offset: 0, + uncompressed_stream_offset: 0, + uncompressed_size: 0, + unpadded_size: 0, + total_size: 0, + reserved_vli1: 0, + reserved_vli2: 0, + reserved_vli3: 0, + reserved_vli4: 0, + reserved_ptr1: core::ptr::null(), + reserved_ptr2: core::ptr::null(), + reserved_ptr3: core::ptr::null(), + reserved_ptr4: core::ptr::null(), + }, + internal: [lzma_index_iter_internal { + p: core::ptr::null(), + }; 6], + }, + pos: 0, + crc32: 0, + }; + index_encoder_reset(::core::ptr::addr_of_mut!(coder), i); + let out_start: size_t = *out_pos; + let mut ret: lzma_ret = index_encode( + ::core::ptr::addr_of_mut!(coder) as *mut c_void, + core::ptr::null(), + core::ptr::null(), + core::ptr::null_mut(), + 0, + out, + out_pos, + out_size, + LZMA_RUN, + ); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + } else { + *out_pos = out_start; + ret = LZMA_PROG_ERROR; + } + ret +} diff --git a/liblzma-rs/src/common/index_hash.rs b/liblzma-rs/src/common/index_hash.rs new file mode 100644 index 00000000..c75d4389 --- /dev/null +++ b/liblzma-rs/src/common/index_hash.rs @@ -0,0 +1,323 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_hash_s { + pub sequence: index_hash_seq, + pub blocks: lzma_index_hash_info, + pub records: lzma_index_hash_info, + pub remaining: lzma_vli, + pub unpadded_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub pos: size_t, + pub crc32: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_hash_info { + pub blocks_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub count: lzma_vli, + pub index_list_size: lzma_vli, + pub check: lzma_check_state, +} +pub type index_hash_seq = c_uint; +pub const SEQ_CRC32: index_hash_seq = 6; +pub const SEQ_PADDING: index_hash_seq = 5; +pub const SEQ_PADDING_INIT: index_hash_seq = 4; +pub const SEQ_UNCOMPRESSED: index_hash_seq = 3; +pub const SEQ_UNPADDED: index_hash_seq = 2; +pub const SEQ_COUNT: index_hash_seq = 1; +pub const SEQ_BLOCK: index_hash_seq = 0; +pub type lzma_index_hash = lzma_index_hash_s; +#[inline] +extern "C" fn index_stream_size( + blocks_size: lzma_vli, + count: lzma_vli, + index_list_size: lzma_vli, +) -> lzma_vli { + (LZMA_STREAM_HEADER_SIZE as lzma_vli) + .wrapping_add(blocks_size) + .wrapping_add(index_size(count, index_list_size)) + .wrapping_add(LZMA_STREAM_HEADER_SIZE as lzma_vli) +} +pub unsafe fn lzma_index_hash_init( + mut index_hash: *mut lzma_index_hash, + allocator: *const lzma_allocator, +) -> *mut lzma_index_hash { + if index_hash.is_null() { + index_hash = + lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_index_hash; + if index_hash.is_null() { + return core::ptr::null_mut(); + } + } + (*index_hash).sequence = SEQ_BLOCK; + (*index_hash).blocks.blocks_size = 0; + (*index_hash).blocks.uncompressed_size = 0; + (*index_hash).blocks.count = 0; + (*index_hash).blocks.index_list_size = 0; + (*index_hash).records.blocks_size = 0; + (*index_hash).records.uncompressed_size = 0; + (*index_hash).records.count = 0; + (*index_hash).records.index_list_size = 0; + (*index_hash).unpadded_size = 0; + (*index_hash).uncompressed_size = 0; + (*index_hash).pos = 0; + (*index_hash).crc32 = 0; + lzma_check_init( + ::core::ptr::addr_of_mut!((*index_hash).blocks.check), + LZMA_CHECK_SHA256, + ); + lzma_check_init( + ::core::ptr::addr_of_mut!((*index_hash).records.check), + LZMA_CHECK_SHA256, + ); + index_hash +} +pub unsafe fn lzma_index_hash_end( + index_hash: *mut lzma_index_hash, + allocator: *const lzma_allocator, +) { + lzma_free(index_hash as *mut c_void, allocator); +} +pub fn lzma_index_hash_size(index_hash: *const lzma_index_hash) -> lzma_vli { + unsafe { + index_size( + (*index_hash).blocks.count, + (*index_hash).blocks.index_list_size, + ) + } +} +unsafe fn hash_append( + info: *mut lzma_index_hash_info, + unpadded_size: lzma_vli, + uncompressed_size: lzma_vli, +) { + (*info).blocks_size = (*info).blocks_size.wrapping_add(vli_ceil4(unpadded_size)); + (*info).uncompressed_size = (*info).uncompressed_size.wrapping_add(uncompressed_size); + (*info).index_list_size = (*info).index_list_size.wrapping_add( + lzma_vli_size(unpadded_size).wrapping_add(lzma_vli_size(uncompressed_size)) as lzma_vli, + ); + (*info).count = (*info).count.wrapping_add(1); + let sizes: [lzma_vli; 2] = [unpadded_size, uncompressed_size]; + lzma_check_update( + ::core::ptr::addr_of_mut!((*info).check), + LZMA_CHECK_SHA256, + ::core::ptr::addr_of!(sizes) as *const lzma_vli as *const u8, + core::mem::size_of::<[lzma_vli; 2]>(), + ); +} +pub unsafe fn lzma_index_hash_append( + index_hash: *mut lzma_index_hash, + unpadded_size: lzma_vli, + uncompressed_size: lzma_vli, +) -> lzma_ret { + if index_hash.is_null() + || (*index_hash).sequence != SEQ_BLOCK + || unpadded_size < UNPADDED_SIZE_MIN + || unpadded_size > UNPADDED_SIZE_MAX + || uncompressed_size > LZMA_VLI_MAX + { + return LZMA_PROG_ERROR; + } + hash_append( + ::core::ptr::addr_of_mut!((*index_hash).blocks), + unpadded_size, + uncompressed_size, + ); + if (*index_hash).blocks.blocks_size > LZMA_VLI_MAX + || (*index_hash).blocks.uncompressed_size > LZMA_VLI_MAX + || index_size( + (*index_hash).blocks.count, + (*index_hash).blocks.index_list_size, + ) > LZMA_BACKWARD_SIZE_MAX + || index_stream_size( + (*index_hash).blocks.blocks_size, + (*index_hash).blocks.count, + (*index_hash).blocks.index_list_size, + ) > LZMA_VLI_MAX + { + return LZMA_DATA_ERROR; + } + LZMA_OK +} +pub unsafe fn lzma_index_hash_decode( + index_hash: *mut lzma_index_hash, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + let mut current_block: u64; + if *in_pos >= in_size { + return LZMA_BUF_ERROR; + } + let in_start: size_t = *in_pos; + let mut ret: lzma_ret = LZMA_OK; + while *in_pos < in_size { + match (*index_hash).sequence { + 0 => { + let byte = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if byte != INDEX_INDICATOR { + return LZMA_DATA_ERROR; + } + (*index_hash).sequence = SEQ_COUNT; + continue; + } + 1 => { + ret = lzma_vli_decode( + ::core::ptr::addr_of_mut!((*index_hash).remaining), + ::core::ptr::addr_of_mut!((*index_hash).pos), + in_0, + in_pos, + in_size, + ); + if ret != LZMA_STREAM_END { + break; + } + if (*index_hash).remaining != (*index_hash).blocks.count { + return LZMA_DATA_ERROR; + } + ret = LZMA_OK; + (*index_hash).pos = 0; + (*index_hash).sequence = (if (*index_hash).remaining == 0 { + SEQ_PADDING_INIT + } else { + SEQ_UNPADDED + }) as index_hash_seq; + continue; + } + 2 | 3 => { + let size: *mut lzma_vli = if (*index_hash).sequence == SEQ_UNPADDED { + ::core::ptr::addr_of_mut!((*index_hash).unpadded_size) + } else { + ::core::ptr::addr_of_mut!((*index_hash).uncompressed_size) + }; + ret = lzma_vli_decode( + size, + ::core::ptr::addr_of_mut!((*index_hash).pos), + in_0, + in_pos, + in_size, + ); + if ret != LZMA_STREAM_END { + break; + } + ret = LZMA_OK; + (*index_hash).pos = 0; + if (*index_hash).sequence == SEQ_UNPADDED { + if (*index_hash).unpadded_size < UNPADDED_SIZE_MIN + || (*index_hash).unpadded_size > UNPADDED_SIZE_MAX + { + return LZMA_DATA_ERROR; + } + (*index_hash).sequence = SEQ_UNCOMPRESSED; + } else { + hash_append( + ::core::ptr::addr_of_mut!((*index_hash).records), + (*index_hash).unpadded_size, + (*index_hash).uncompressed_size, + ); + if (*index_hash).blocks.blocks_size < (*index_hash).records.blocks_size + || (*index_hash).blocks.uncompressed_size + < (*index_hash).records.uncompressed_size + || (*index_hash).blocks.index_list_size + < (*index_hash).records.index_list_size + { + return LZMA_DATA_ERROR; + } + (*index_hash).remaining -= 1; + (*index_hash).sequence = (if (*index_hash).remaining == 0 { + SEQ_PADDING_INIT + } else { + SEQ_UNPADDED + }) as index_hash_seq; + } + continue; + } + 4 => { + (*index_hash).pos = ((4_u64).wrapping_sub(index_size_unpadded( + (*index_hash).records.count, + (*index_hash).records.index_list_size, + )) & 3) as size_t; + (*index_hash).sequence = SEQ_PADDING; + current_block = 12753679906265593574; + } + 5 => { + current_block = 12753679906265593574; + } + 6 => { + current_block = 88292361528268742; + } + _ => return LZMA_PROG_ERROR, + } + match current_block { + 12753679906265593574 => { + if (*index_hash).pos > 0 { + (*index_hash).pos -= 1; + let byte = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if byte != 0 { + return LZMA_DATA_ERROR; + } + continue; + } else { + if (*index_hash).blocks.blocks_size != (*index_hash).records.blocks_size + || (*index_hash).blocks.uncompressed_size + != (*index_hash).records.uncompressed_size + || (*index_hash).blocks.index_list_size + != (*index_hash).records.index_list_size + { + return LZMA_DATA_ERROR; + } + lzma_check_finish( + ::core::ptr::addr_of_mut!((*index_hash).blocks.check), + LZMA_CHECK_SHA256, + ); + lzma_check_finish( + ::core::ptr::addr_of_mut!((*index_hash).records.check), + LZMA_CHECK_SHA256, + ); + if memcmp( + ::core::ptr::addr_of_mut!((*index_hash).blocks.check.buffer.u8_0) + as *const c_void, + ::core::ptr::addr_of_mut!((*index_hash).records.check.buffer.u8_0) + as *const c_void, + lzma_check_size(LZMA_CHECK_SHA256) as size_t, + ) != 0 + { + return LZMA_DATA_ERROR; + } + (*index_hash).crc32 = lzma_crc32( + in_0.offset(in_start as isize), + *in_pos - in_start, + (*index_hash).crc32, + ); + (*index_hash).sequence = SEQ_CRC32; + } + } + _ => {} + } + loop { + if *in_pos == in_size { + return LZMA_OK; + } + let val = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if (*index_hash).crc32 >> ((*index_hash).pos * 8) & 0xff != val as u32 { + return LZMA_DATA_ERROR; + } + (*index_hash).pos += 1; + if (*index_hash).pos >= 4 { + break; + } + } + return LZMA_STREAM_END; + } + let in_used: size_t = *in_pos - in_start; + if in_used > 0 { + (*index_hash).crc32 = + lzma_crc32(in_0.offset(in_start as isize), in_used, (*index_hash).crc32); + } + ret +} diff --git a/liblzma-rs/src/common/lzip_decoder.rs b/liblzma-rs/src/common/lzip_decoder.rs new file mode 100644 index 00000000..e74bd324 --- /dev/null +++ b/liblzma-rs/src/common/lzip_decoder.rs @@ -0,0 +1,404 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lzip_coder { + pub sequence: lzip_decoder_seq, + pub version: u32, + pub crc32: u32, + pub uncompressed_size: u64, + pub member_size: u64, + pub memlimit: u64, + pub memusage: u64, + pub tell_any_check: bool, + pub ignore_check: bool, + pub concatenated: bool, + pub first_member: bool, + pub pos: size_t, + pub buffer: [u8; 20], + pub options: lzma_options_lzma, + pub lzma_decoder: lzma_next_coder, +} +pub type lzip_decoder_seq = c_uint; +pub const SEQ_MEMBER_FOOTER: lzip_decoder_seq = 5; +pub const SEQ_LZMA_STREAM: lzip_decoder_seq = 4; +pub const SEQ_CODER_INIT: lzip_decoder_seq = 3; +pub const SEQ_DICT_SIZE: lzip_decoder_seq = 2; +pub const SEQ_VERSION: lzip_decoder_seq = 1; +pub const SEQ_ID_STRING: lzip_decoder_seq = 0; +#[inline] +extern "C" fn read64le(buf: *const u8) -> u64 { + return unsafe { + let mut num: u64 = *buf as u64; + num |= (*buf.offset(1) as u64) << 8; + num |= (*buf.offset(2) as u64) << 16; + num |= (*buf.offset(3) as u64) << 24; + num |= (*buf.offset(4) as u64) << 32; + num |= (*buf.offset(5) as u64) << 40; + num |= (*buf.offset(6) as u64) << 48; + num |= (*buf.offset(7) as u64) << 56; + num + }; +} +pub const LZIP_V0_FOOTER_SIZE: u32 = 12; +pub const LZIP_V1_FOOTER_SIZE: u32 = 20; +pub const LZIP_LC: u32 = 3; +pub const LZIP_LP: u32 = 0; +pub const LZIP_PB: u32 = 2; +unsafe extern "C" fn lzip_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_lzip_coder = coder_ptr as *mut lzma_lzip_coder; + loop { + let mut current_block_80: u64; + match (*coder).sequence { + 0 => { + let lzip_id_string: [u8; 4] = [0x4c as u8, 0x5a as u8, 0x49 as u8, 0x50 as u8]; + while (*coder).pos < core::mem::size_of::<[u8; 4]>() { + if *in_pos >= in_size { + return if !(*coder).first_member && action == LZMA_FINISH { + LZMA_STREAM_END + } else { + LZMA_OK + }; + } + if *in_0.offset(*in_pos as isize) != lzip_id_string[(*coder).pos as usize] { + return if !(*coder).first_member { + LZMA_STREAM_END + } else { + LZMA_FORMAT_ERROR + }; + } + *in_pos += 1; + (*coder).pos += 1; + } + (*coder).pos = 0; + (*coder).crc32 = 0; + (*coder).uncompressed_size = 0; + (*coder).member_size = core::mem::size_of::<[u8; 4]>() as u64; + (*coder).sequence = SEQ_VERSION; + current_block_80 = 11220331375136032509; + } + 1 => { + current_block_80 = 11220331375136032509; + } + 2 => { + current_block_80 = 2770508642018830579; + } + 3 => { + current_block_80 = 15476230294461844687; + } + 4 => { + current_block_80 = 13394712405657322686; + } + 5 => { + current_block_80 = 13619784596304402172; + } + _ => return LZMA_PROG_ERROR, + } + match current_block_80 { + 11220331375136032509 => { + if *in_pos >= in_size { + return LZMA_OK; + } + (*coder).version = *in_0.offset(*in_pos as isize) as u32; + *in_pos += 1; + if (*coder).version > 1 { + return LZMA_OPTIONS_ERROR; + } + (*coder).member_size += 1; + (*coder).sequence = SEQ_DICT_SIZE; + if (*coder).tell_any_check { + return LZMA_GET_CHECK; + } + current_block_80 = 2770508642018830579; + } + _ => {} + } + match current_block_80 { + 2770508642018830579 => { + if *in_pos >= in_size { + return LZMA_OK; + } + let ds: u32 = *in_0.offset(*in_pos as isize) as u32; + *in_pos += 1; + (*coder).member_size += 1; + let b2log: u32 = ds & 0x1f; + let fracnum: u32 = ds >> 5; + if b2log < 12 || b2log > 29 || b2log == 12 && fracnum > 0 { + return LZMA_DATA_ERROR; + } + (*coder).options.dict_size = (1u32 << b2log) - (fracnum << (b2log - 4)); + (*coder).options.preset_dict = core::ptr::null(); + (*coder).options.lc = LZIP_LC; + (*coder).options.lp = LZIP_LP; + (*coder).options.pb = LZIP_PB; + (*coder).memusage = lzma_lzma_decoder_memusage_nocheck(::core::ptr::addr_of_mut!( + (*coder).options + ) + as *const c_void) + .wrapping_add(LZMA_MEMUSAGE_BASE); + (*coder).sequence = SEQ_CODER_INIT; + current_block_80 = 15476230294461844687; + } + _ => {} + } + match current_block_80 { + 15476230294461844687 => { + if (*coder).memusage > (*coder).memlimit { + return LZMA_MEMLIMIT_ERROR; + } + let filters: [lzma_filter_info; 2] = [ + lzma_filter_info_s { + id: LZMA_FILTER_LZMA1, + init: Some( + lzma_lzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) + -> lzma_ret, + ), + options: ::core::ptr::addr_of_mut!((*coder).options) as *mut c_void, + }, + lzma_filter_info_s { + id: 0, + init: None, + options: core::ptr::null_mut(), + }, + ]; + let ret_: lzma_ret = lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).lzma_decoder), + allocator, + ::core::ptr::addr_of!(filters) as *const lzma_filter_info, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).crc32 = 0; + (*coder).sequence = SEQ_LZMA_STREAM; + current_block_80 = 13394712405657322686; + } + _ => {} + } + match current_block_80 { + 13394712405657322686 => { + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + let ret: lzma_ret = (*coder).lzma_decoder.code.unwrap()( + (*coder).lzma_decoder.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + let out_used: size_t = *out_pos - out_start; + (*coder).member_size += (*in_pos - in_start) as u64; + (*coder).uncompressed_size += out_used as u64; + if !(*coder).ignore_check && out_used > 0 { + (*coder).crc32 = + lzma_crc32(out.offset(out_start as isize), out_used, (*coder).crc32); + } + if ret != LZMA_STREAM_END { + return ret; + } + (*coder).sequence = SEQ_MEMBER_FOOTER; + } + _ => {} + } + let footer_size: size_t = (if (*coder).version == 0 { + LZIP_V0_FOOTER_SIZE + } else { + LZIP_V1_FOOTER_SIZE + }) as size_t; + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + footer_size, + ); + if (*coder).pos < footer_size { + return LZMA_OK; + } + (*coder).pos = 0; + (*coder).member_size += footer_size as u64; + if !(*coder).ignore_check + && (*coder).crc32 + != read32le((::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8) as *mut u8) + { + return LZMA_DATA_ERROR; + } + if (*coder).uncompressed_size + != read64le( + (::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8).offset(4) as *mut u8, + ) + { + return LZMA_DATA_ERROR; + } + if (*coder).version > 0 { + if (*coder).member_size + != read64le( + (::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8).offset(12) as *mut u8, + ) + { + return LZMA_DATA_ERROR; + } + } + if !(*coder).concatenated { + return LZMA_STREAM_END; + } + (*coder).first_member = false; + (*coder).sequence = SEQ_ID_STRING; + } +} +unsafe extern "C" fn lzip_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_lzip_coder = coder_ptr as *mut lzma_lzip_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).lzma_decoder), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +extern "C" fn lzip_decoder_get_check(_coder_ptr: *const c_void) -> lzma_check { + LZMA_CHECK_CRC32 +} +unsafe extern "C" fn lzip_decoder_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_lzip_coder = coder_ptr as *mut lzma_lzip_coder; + *memusage = (*coder).memusage; + *old_memlimit = (*coder).memlimit; + if new_memlimit != 0 { + if new_memlimit < (*coder).memusage { + return LZMA_MEMLIMIT_ERROR; + } + (*coder).memlimit = new_memlimit; + } + LZMA_OK +} +pub unsafe extern "C" fn lzma_lzip_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + memlimit: u64, + flags: u32, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn(*mut lzma_next_coder, *const lzma_allocator, u64, u32) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_lzip_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u32, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn(*mut lzma_next_coder, *const lzma_allocator, u64, u32) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_lzip_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u32, + ) -> lzma_ret, + )); + if flags & !(LZMA_SUPPORTED_FLAGS as u32) != 0 { + return LZMA_OPTIONS_ERROR; + } + let mut coder: *mut lzma_lzip_coder = (*next).coder as *mut lzma_lzip_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + lzip_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + lzip_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).get_check = + Some(lzip_decoder_get_check as unsafe extern "C" fn(*const c_void) -> lzma_check); + (*next).memconfig = Some( + lzip_decoder_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*coder).lzma_decoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + (*coder).sequence = SEQ_ID_STRING; + (*coder).memlimit = if 1 > memlimit { 1 } else { memlimit }; + (*coder).memusage = LZMA_MEMUSAGE_BASE; + (*coder).tell_any_check = flags & LZMA_TELL_ANY_CHECK as u32 != 0; + (*coder).ignore_check = flags & LZMA_IGNORE_CHECK as u32 != 0; + (*coder).concatenated = flags & LZMA_CONCATENATED as u32 != 0; + (*coder).first_member = true; + (*coder).pos = 0; + LZMA_OK +} +pub unsafe fn lzma_lzip_decoder(strm: *mut lzma_stream, memlimit: u64, flags: u32) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_lzip_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + memlimit, + flags, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/microlzma_decoder.rs b/liblzma-rs/src/common/microlzma_decoder.rs new file mode 100644 index 00000000..a29d2c9b --- /dev/null +++ b/liblzma-rs/src/common/microlzma_decoder.rs @@ -0,0 +1,282 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_microlzma_coder { + pub lzma: lzma_next_coder, + pub comp_size: u64, + pub uncomp_size: lzma_vli, + pub dict_size: u32, + pub uncomp_size_is_exact: bool, + pub props_decoded: bool, +} +unsafe extern "C" fn microlzma_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + mut in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + mut out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_microlzma_coder = coder_ptr as *mut lzma_microlzma_coder; + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + if (in_size - *in_pos) as u64 > (*coder).comp_size { + in_size = *in_pos + (*coder).comp_size as size_t; + } + if !(*coder).uncomp_size_is_exact && (out_size - *out_pos) as lzma_vli > (*coder).uncomp_size { + out_size = *out_pos + (*coder).uncomp_size as size_t; + } + if !(*coder).props_decoded { + if *in_pos >= in_size { + return LZMA_OK; + } + let mut options: lzma_options_lzma = lzma_options_lzma { + dict_size: (*coder).dict_size, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: UINT32_MAX, + ext_size_high: UINT32_MAX, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }; + if (*coder).uncomp_size_is_exact { + options.ext_size_low = (*coder).uncomp_size as u32; + options.ext_size_high = ((*coder).uncomp_size >> 32) as u32; + } + if lzma_lzma_lclppb_decode( + ::core::ptr::addr_of_mut!(options), + !*in_0.offset(*in_pos as isize), + ) { + return LZMA_OPTIONS_ERROR; + } + *in_pos += 1; + let mut filters: [lzma_filter_info; 2] = [ + lzma_filter_info_s { + id: LZMA_FILTER_LZMA1EXT, + init: Some( + lzma_lzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + options: ::core::ptr::addr_of_mut!(options) as *mut c_void, + }, + lzma_filter_info_s { + id: 0, + init: None, + options: core::ptr::null_mut(), + }, + ]; + let ret_: lzma_ret = lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).lzma), + allocator, + ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter_info, + ); + if ret_ != LZMA_OK { + return ret_; + } + let dummy_in: u8 = 0; + let mut dummy_in_pos: size_t = 0; + if (*coder).lzma.code.unwrap()( + (*coder).lzma.coder, + allocator, + ::core::ptr::addr_of!(dummy_in), + ::core::ptr::addr_of_mut!(dummy_in_pos), + 1, + out, + out_pos, + out_size, + LZMA_RUN, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + (*coder).props_decoded = true; + } + let mut ret: lzma_ret = (*coder).lzma.code.unwrap()( + (*coder).lzma.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + (*coder).comp_size -= (*in_pos - in_start) as u64; + if (*coder).uncomp_size_is_exact { + if ret == LZMA_STREAM_END && (*coder).comp_size != 0 { + ret = LZMA_DATA_ERROR; + } + } else { + (*coder).uncomp_size -= (*out_pos - out_start) as lzma_vli; + if ret == LZMA_STREAM_END { + ret = LZMA_DATA_ERROR; + } else if (*coder).uncomp_size == 0 { + ret = LZMA_STREAM_END; + } + } + ret +} +unsafe extern "C" fn microlzma_decoder_end( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, +) { + let coder: *mut lzma_microlzma_coder = coder_ptr as *mut lzma_microlzma_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).lzma), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn microlzma_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + comp_size: u64, + uncomp_size: u64, + uncomp_size_is_exact: bool, + dict_size: u32, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u64, + bool, + u32, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + microlzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u64, + bool, + u32, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u64, + bool, + u32, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + microlzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u64, + bool, + u32, + ) -> lzma_ret, + )); + let mut coder: *mut lzma_microlzma_coder = (*next).coder as *mut lzma_microlzma_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + microlzma_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + microlzma_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*coder).lzma = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + if uncomp_size > LZMA_VLI_MAX as u64 { + return LZMA_OPTIONS_ERROR; + } + (*coder).comp_size = comp_size; + (*coder).uncomp_size = uncomp_size as lzma_vli; + (*coder).uncomp_size_is_exact = uncomp_size_is_exact; + (*coder).dict_size = dict_size; + (*coder).props_decoded = false; + LZMA_OK +} +pub unsafe fn lzma_microlzma_decoder( + strm: *mut lzma_stream, + comp_size: u64, + uncomp_size: u64, + uncomp_size_is_exact: lzma_bool, + dict_size: u32, +) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = microlzma_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + comp_size, + uncomp_size, + uncomp_size_is_exact != 0, + dict_size, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/microlzma_encoder.rs b/liblzma-rs/src/common/microlzma_encoder.rs new file mode 100644 index 00000000..207b9fde --- /dev/null +++ b/liblzma-rs/src/common/microlzma_encoder.rs @@ -0,0 +1,196 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_microlzma_coder { + pub lzma: lzma_next_coder, + pub props: u8, +} +unsafe extern "C" fn microlzma_encode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_microlzma_coder = coder_ptr as *mut lzma_microlzma_coder; + let out_start: size_t = *out_pos; + let in_start: size_t = *in_pos; + let mut uncomp_size: u64 = 0; + let set_out_limit = if let Some(set_out_limit) = (*coder).lzma.set_out_limit { + set_out_limit + } else { + return LZMA_PROG_ERROR; + }; + let code = if let Some(code) = (*coder).lzma.code { + code + } else { + return LZMA_PROG_ERROR; + }; + if set_out_limit( + (*coder).lzma.coder, + ::core::ptr::addr_of_mut!(uncomp_size), + (out_size - *out_pos) as u64, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + let ret: lzma_ret = code( + (*coder).lzma.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + if ret != LZMA_STREAM_END { + if ret == LZMA_OK { + return LZMA_PROG_ERROR; + } + return ret; + } + *out.offset(out_start as isize) = !(*coder).props; + *in_pos = in_start + uncomp_size as size_t; + ret +} +unsafe extern "C" fn microlzma_encoder_end( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, +) { + let coder: *mut lzma_microlzma_coder = coder_ptr as *mut lzma_microlzma_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).lzma), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn microlzma_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + options: *const lzma_options_lzma, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + microlzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + microlzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_options_lzma, + ) -> lzma_ret, + )); + let mut coder: *mut lzma_microlzma_coder = (*next).coder as *mut lzma_microlzma_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + microlzma_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + microlzma_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*coder).lzma = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + if lzma_lzma_lclppb_encode(options, ::core::ptr::addr_of_mut!((*coder).props)) { + return LZMA_OPTIONS_ERROR; + } + let filters: [lzma_filter_info; 2] = [ + lzma_filter_info_s { + id: LZMA_FILTER_LZMA1, + init: Some( + lzma_lzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, + ), + options: options as *mut c_void, + }, + lzma_filter_info_s { + id: 0, + init: None, + options: core::ptr::null_mut(), + }, + ]; + lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).lzma), + allocator, + ::core::ptr::addr_of!(filters) as *const lzma_filter_info, + ) +} +pub unsafe fn lzma_microlzma_encoder( + strm: *mut lzma_stream, + options: *const lzma_options_lzma, +) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = microlzma_encoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + options, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/mod.rs b/liblzma-rs/src/common/mod.rs new file mode 100644 index 00000000..eec2ca1a --- /dev/null +++ b/liblzma-rs/src/common/mod.rs @@ -0,0 +1,48 @@ +pub mod alone_decoder; +pub mod alone_encoder; +pub mod auto_decoder; +pub mod block_buffer_decoder; +pub mod block_buffer_encoder; +pub mod block_decoder; +pub mod block_encoder; +pub mod block_header_decoder; +pub mod block_header_encoder; +pub mod block_util; +pub mod common; +pub mod easy_buffer_encoder; +pub mod easy_decoder_memusage; +pub mod easy_encoder; +pub mod easy_encoder_memusage; +pub mod easy_preset; +pub mod file_info; +pub mod filter_buffer_decoder; +pub mod filter_buffer_encoder; +pub mod filter_common; +pub mod filter_decoder; +pub mod filter_encoder; +pub mod filter_flags_decoder; +pub mod filter_flags_encoder; +pub mod hardware_cputhreads; +pub mod hardware_physmem; +pub mod index; +pub mod index_decoder; +pub mod index_encoder; +pub mod index_hash; +pub mod lzip_decoder; +pub mod microlzma_decoder; +pub mod microlzma_encoder; +pub mod outqueue; +pub mod stream_buffer_decoder; +pub mod stream_buffer_encoder; +pub mod stream_decoder; +pub mod stream_decoder_mt; +pub mod stream_encoder; +pub mod stream_encoder_mt; +pub mod stream_flags_common; +pub mod stream_flags_decoder; +pub mod stream_flags_encoder; +pub mod stream_mt; +pub mod string_conversion; +pub mod vli_decoder; +pub mod vli_encoder; +pub mod vli_size; diff --git a/liblzma-rs/src/common/outqueue.rs b/liblzma-rs/src/common/outqueue.rs new file mode 100644 index 00000000..7f1c3e15 --- /dev/null +++ b/liblzma-rs/src/common/outqueue.rs @@ -0,0 +1,174 @@ +use crate::types::*; +pub fn lzma_outq_memusage(buf_size_max: u64, threads: u32) -> u64 { + let limit: u64 = UINT64_MAX / (2 * 16384) as u64 / 2; + if threads > LZMA_THREADS_MAX || buf_size_max > limit { + return UINT64_MAX; + } + (2u32 * threads) as u64 * lzma_outq_outbuf_memusage(buf_size_max as size_t) +} +unsafe fn move_head_to_cache(outq: *mut lzma_outq, allocator: *const lzma_allocator) { + let buf: *mut lzma_outbuf = (*outq).head; + (*outq).head = (*buf).next; + if (*outq).head.is_null() { + (*outq).tail = core::ptr::null_mut(); + } + if !(*outq).cache.is_null() && (*(*outq).cache).allocated != (*buf).allocated { + lzma_outq_clear_cache(outq, allocator); + } + (*buf).next = (*outq).cache; + (*outq).cache = buf; + (*outq).bufs_in_use -= 1; + (*outq).mem_in_use -= lzma_outq_outbuf_memusage((*buf).allocated); +} +unsafe fn free_one_cached_buffer(outq: *mut lzma_outq, allocator: *const lzma_allocator) { + let buf: *mut lzma_outbuf = (*outq).cache; + (*outq).cache = (*buf).next; + (*outq).bufs_allocated -= 1; + (*outq).mem_allocated -= lzma_outq_outbuf_memusage((*buf).allocated); + crate::alloc::internal_free(buf as *mut c_void, allocator); +} +pub unsafe fn lzma_outq_clear_cache(outq: *mut lzma_outq, allocator: *const lzma_allocator) { + while !(*outq).cache.is_null() { + free_one_cached_buffer(outq, allocator); + } +} +pub unsafe fn lzma_outq_clear_cache2( + outq: *mut lzma_outq, + allocator: *const lzma_allocator, + keep_size: size_t, +) { + if (*outq).cache.is_null() { + return; + } + while !(*(*outq).cache).next.is_null() { + free_one_cached_buffer(outq, allocator); + } + if (*(*outq).cache).allocated != keep_size { + free_one_cached_buffer(outq, allocator); + } +} +pub unsafe fn lzma_outq_init( + outq: *mut lzma_outq, + allocator: *const lzma_allocator, + threads: u32, +) -> lzma_ret { + if threads > LZMA_THREADS_MAX { + return LZMA_OPTIONS_ERROR; + } + let bufs_limit: u32 = 2u32 * threads; + while !(*outq).head.is_null() { + move_head_to_cache(outq, allocator); + } + while bufs_limit < (*outq).bufs_allocated { + free_one_cached_buffer(outq, allocator); + } + (*outq).bufs_limit = bufs_limit; + (*outq).read_pos = 0; + LZMA_OK +} +pub unsafe fn lzma_outq_end(outq: *mut lzma_outq, allocator: *const lzma_allocator) { + while !(*outq).head.is_null() { + move_head_to_cache(outq, allocator); + } + lzma_outq_clear_cache(outq, allocator); +} +pub unsafe fn lzma_outq_prealloc_buf( + outq: *mut lzma_outq, + allocator: *const lzma_allocator, + size: size_t, +) -> lzma_ret { + if !(*outq).cache.is_null() && (*(*outq).cache).allocated == size { + return LZMA_OK; + } + if size > (SIZE_MAX as usize) - core::mem::size_of::() { + return LZMA_MEM_ERROR; + } + let alloc_size: size_t = lzma_outq_outbuf_memusage(size) as size_t; + lzma_outq_clear_cache(outq, allocator); + (*outq).cache = crate::alloc::internal_alloc_bytes(alloc_size, allocator) as *mut lzma_outbuf; + if (*outq).cache.is_null() { + return LZMA_MEM_ERROR; + } + (*(*outq).cache).next = core::ptr::null_mut(); + (*(*outq).cache).allocated = size; + (*outq).bufs_allocated += 1; + (*outq).mem_allocated += alloc_size as u64; + LZMA_OK +} +pub unsafe fn lzma_outq_get_buf(outq: *mut lzma_outq, worker: *mut c_void) -> *mut lzma_outbuf { + let buf: *mut lzma_outbuf = (*outq).cache; + (*outq).cache = (*buf).next; + (*buf).next = core::ptr::null_mut(); + if !(*outq).tail.is_null() { + (*(*outq).tail).next = buf; + } else { + (*outq).head = buf; + } + (*outq).tail = buf; + (*buf).worker = worker; + (*buf).finished = false; + (*buf).finish_ret = LZMA_STREAM_END; + (*buf).pos = 0; + (*buf).decoder_in_pos = 0; + (*buf).unpadded_size = 0; + (*buf).uncompressed_size = 0; + (*outq).bufs_in_use += 1; + (*outq).mem_in_use += lzma_outq_outbuf_memusage((*buf).allocated); + buf +} +pub unsafe fn lzma_outq_is_readable(outq: *const lzma_outq) -> bool { + if (*outq).head.is_null() { + return false; + } + (*outq).read_pos < (*(*outq).head).pos || (*(*outq).head).finished +} +pub unsafe fn lzma_outq_read( + outq: *mut lzma_outq, + allocator: *const lzma_allocator, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + unpadded_size: *mut lzma_vli, + uncompressed_size: *mut lzma_vli, +) -> lzma_ret { + if (*outq).bufs_in_use == 0 { + return LZMA_OK; + } + let buf: *mut lzma_outbuf = (*outq).head; + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*buf).buf) as *mut u8, + ::core::ptr::addr_of_mut!((*outq).read_pos), + (*buf).pos, + out, + out_pos, + out_size, + ); + if !(*buf).finished || (*outq).read_pos < (*buf).pos { + return LZMA_OK; + } + if !unpadded_size.is_null() { + *unpadded_size = (*buf).unpadded_size; + } + if !uncompressed_size.is_null() { + *uncompressed_size = (*buf).uncompressed_size; + } + let finish_ret: lzma_ret = (*buf).finish_ret; + move_head_to_cache(outq, allocator); + (*outq).read_pos = 0; + finish_ret +} +pub unsafe fn lzma_outq_enable_partial_output( + outq: *mut lzma_outq, + enable_partial_output: Option ()>, +) { + let enable_partial_output = if let Some(enable_partial_output) = enable_partial_output { + enable_partial_output + } else { + return; + }; + + if !(*outq).head.is_null() && !(*(*outq).head).finished && !(*(*outq).head).worker.is_null() { + enable_partial_output((*(*outq).head).worker); + (*(*outq).head).worker = core::ptr::null_mut(); + } +} diff --git a/liblzma-rs/src/common/stream_buffer_decoder.rs b/liblzma-rs/src/common/stream_buffer_decoder.rs new file mode 100644 index 00000000..36053c0d --- /dev/null +++ b/liblzma-rs/src/common/stream_buffer_decoder.rs @@ -0,0 +1,93 @@ +use crate::types::*; +pub unsafe fn lzma_stream_buffer_decode( + memlimit: *mut u64, + flags: u32, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if in_pos.is_null() + || in_0.is_null() && *in_pos != in_size + || *in_pos > in_size + || out_pos.is_null() + || out.is_null() && *out_pos != out_size + || *out_pos > out_size + { + return LZMA_PROG_ERROR; + } + if flags & LZMA_TELL_ANY_CHECK as u32 != 0 { + return LZMA_PROG_ERROR; + } + let mut stream_decoder: lzma_next_coder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + let mut ret: lzma_ret = lzma_stream_decoder_init( + ::core::ptr::addr_of_mut!(stream_decoder), + allocator, + *memlimit, + flags, + ); + if ret == LZMA_OK { + let code = if let Some(code) = stream_decoder.code { + code + } else { + lzma_next_end(::core::ptr::addr_of_mut!(stream_decoder), allocator); + return LZMA_PROG_ERROR; + }; + let in_start: size_t = *in_pos; + let out_start: size_t = *out_pos; + ret = code( + stream_decoder.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + LZMA_FINISH, + ); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + } else { + *in_pos = in_start; + *out_pos = out_start; + if ret == LZMA_OK { + if *in_pos == in_size { + ret = LZMA_DATA_ERROR; + } else { + ret = LZMA_BUF_ERROR; + } + } else if ret == LZMA_MEMLIMIT_ERROR { + let mut memusage: u64 = 0; + let memconfig = if let Some(memconfig) = stream_decoder.memconfig { + memconfig + } else { + lzma_next_end(::core::ptr::addr_of_mut!(stream_decoder), allocator); + return LZMA_PROG_ERROR; + }; + memconfig( + stream_decoder.coder, + memlimit, + ::core::ptr::addr_of_mut!(memusage), + 0, + ); + } + } + } + lzma_next_end(::core::ptr::addr_of_mut!(stream_decoder), allocator); + ret +} diff --git a/liblzma-rs/src/common/stream_buffer_encoder.rs b/liblzma-rs/src/common/stream_buffer_encoder.rs new file mode 100644 index 00000000..b89031b8 --- /dev/null +++ b/liblzma-rs/src/common/stream_buffer_encoder.rs @@ -0,0 +1,148 @@ +use crate::common::block_buffer_encoder::{lzma_block_buffer_bound, lzma_block_buffer_encode}; +use crate::common::index_encoder::lzma_index_buffer_encode; +use crate::types::*; +pub const INDEX_BOUND: u32 = 1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 4 + 3 & !(3); +pub const HEADERS_BOUND: u32 = 2 * LZMA_STREAM_HEADER_SIZE + INDEX_BOUND; +pub fn lzma_stream_buffer_bound(uncompressed_size: size_t) -> size_t { + let block_bound: size_t = lzma_block_buffer_bound(uncompressed_size) as size_t; + if block_bound == 0 { + return 0; + } + let stream_bound_max: size_t = core::cmp::min(size_t::MAX, LZMA_VLI_MAX as size_t); + if stream_bound_max - block_bound < HEADERS_BOUND as size_t { + return 0; + } + block_bound + HEADERS_BOUND as size_t +} +pub unsafe fn lzma_stream_buffer_encode( + filters: *mut lzma_filter, + check: lzma_check, + allocator: *const lzma_allocator, + in_0: *const u8, + in_size: size_t, + out: *mut u8, + out_pos_ptr: *mut size_t, + mut out_size: size_t, +) -> lzma_ret { + if filters.is_null() + || check > LZMA_CHECK_ID_MAX + || in_0.is_null() && in_size != 0 + || out.is_null() + || out_pos_ptr.is_null() + || *out_pos_ptr > out_size + { + return LZMA_PROG_ERROR; + } + if lzma_check_is_supported(check) == 0 { + return LZMA_UNSUPPORTED_CHECK; + } + let mut out_pos: size_t = *out_pos_ptr; + if out_size - out_pos <= (2 * LZMA_STREAM_HEADER_SIZE) as size_t { + return LZMA_BUF_ERROR; + } + out_size -= LZMA_STREAM_HEADER_SIZE as size_t; + let mut stream_flags: lzma_stream_flags = lzma_stream_flags { + version: 0, + backward_size: 0, + check: check, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_bool1: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + reserved_int1: 0, + reserved_int2: 0, + }; + if lzma_stream_header_encode( + ::core::ptr::addr_of_mut!(stream_flags), + out.offset(out_pos as isize), + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + out_pos += LZMA_STREAM_HEADER_SIZE as size_t; + let mut block: lzma_block = lzma_block { + version: 0, + header_size: 0, + check: check, + compressed_size: 0, + uncompressed_size: 0, + filters: filters, + raw_check: [0; 64], + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + reserved_ptr3: core::ptr::null_mut(), + reserved_int1: 0, + reserved_int2: 0, + reserved_int3: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + ignore_check: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + }; + if in_size > 0 { + let ret_: lzma_ret = lzma_block_buffer_encode( + ::core::ptr::addr_of_mut!(block), + allocator, + in_0, + in_size, + out, + ::core::ptr::addr_of_mut!(out_pos), + out_size, + ); + if ret_ != LZMA_OK { + return ret_; + } + } + let i: *mut lzma_index = lzma_index_init(allocator); + if i.is_null() { + return LZMA_MEM_ERROR; + } + let mut ret: lzma_ret = LZMA_OK; + if in_size > 0 { + ret = lzma_index_append( + i, + allocator, + lzma_block_unpadded_size(::core::ptr::addr_of_mut!(block)), + block.uncompressed_size, + ); + } + if ret == LZMA_OK { + ret = lzma_index_buffer_encode(i, out, ::core::ptr::addr_of_mut!(out_pos), out_size); + stream_flags.backward_size = lzma_index_size(i); + } + lzma_index_end(i, allocator); + if ret != LZMA_OK { + return ret; + } + if lzma_stream_footer_encode( + ::core::ptr::addr_of_mut!(stream_flags), + out.offset(out_pos as isize), + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + out_pos += LZMA_STREAM_HEADER_SIZE as size_t; + *out_pos_ptr = out_pos; + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_decoder.rs b/liblzma-rs/src/common/stream_decoder.rs new file mode 100644 index 00000000..e8663905 --- /dev/null +++ b/liblzma-rs/src/common/stream_decoder.rs @@ -0,0 +1,471 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_stream_coder { + pub sequence: stream_decoder_seq, + pub block_decoder: lzma_next_coder, + pub block_options: lzma_block, + pub stream_flags: lzma_stream_flags, + pub index_hash: *mut lzma_index_hash, + pub memlimit: u64, + pub memusage: u64, + pub tell_no_check: bool, + pub tell_unsupported_check: bool, + pub tell_any_check: bool, + pub ignore_check: bool, + pub concatenated: bool, + pub first_stream: bool, + pub pos: size_t, + pub buffer: [u8; LZMA_BLOCK_HEADER_SIZE_MAX as usize], +} +pub type stream_decoder_seq = c_uint; +pub const SEQ_STREAM_PADDING: stream_decoder_seq = 6; +pub const SEQ_STREAM_FOOTER: stream_decoder_seq = 5; +pub const SEQ_INDEX: stream_decoder_seq = 4; +pub const SEQ_BLOCK_RUN: stream_decoder_seq = 3; +pub const SEQ_BLOCK_INIT: stream_decoder_seq = 2; +pub const SEQ_BLOCK_HEADER: stream_decoder_seq = 1; +pub const SEQ_STREAM_HEADER: stream_decoder_seq = 0; +unsafe fn stream_decoder_reset( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, +) -> lzma_ret { + (*coder).index_hash = lzma_index_hash_init((*coder).index_hash, allocator); + if (*coder).index_hash.is_null() { + return LZMA_MEM_ERROR; + } + (*coder).sequence = SEQ_STREAM_HEADER; + (*coder).pos = 0; + LZMA_OK +} +unsafe extern "C" fn stream_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + loop { + let mut current_block_100: u64; + match (*coder).sequence { + 0 => { + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + LZMA_STREAM_HEADER_SIZE as size_t, + ); + if (*coder).pos < LZMA_STREAM_HEADER_SIZE as size_t { + return LZMA_OK; + } + (*coder).pos = 0; + let ret: lzma_ret = lzma_stream_header_decode( + ::core::ptr::addr_of_mut!((*coder).stream_flags), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret != LZMA_OK { + return if ret == LZMA_FORMAT_ERROR && !(*coder).first_stream { + LZMA_DATA_ERROR + } else { + ret + }; + } + (*coder).first_stream = false; + (*coder).block_options.check = (*coder).stream_flags.check; + (*coder).sequence = SEQ_BLOCK_HEADER; + if (*coder).tell_no_check && (*coder).stream_flags.check == LZMA_CHECK_NONE { + return LZMA_NO_CHECK; + } + if (*coder).tell_unsupported_check + && lzma_check_is_supported((*coder).stream_flags.check) == 0 + { + return LZMA_UNSUPPORTED_CHECK; + } + if (*coder).tell_any_check { + return LZMA_GET_CHECK; + } + current_block_100 = 4166486009154926805; + } + 1 => { + current_block_100 = 4166486009154926805; + } + 2 => { + current_block_100 = 3500765272169221397; + } + 3 => { + current_block_100 = 721385680381463314; + } + 4 => { + if *in_pos >= in_size { + return LZMA_OK; + } + let ret_2: lzma_ret = + lzma_index_hash_decode((*coder).index_hash, in_0, in_pos, in_size); + if ret_2 != LZMA_STREAM_END { + return ret_2; + } + (*coder).sequence = SEQ_STREAM_FOOTER; + current_block_100 = 17861496924281778896; + } + 5 => { + current_block_100 = 17861496924281778896; + } + 6 => { + current_block_100 = 15462640364611497761; + } + _ => return LZMA_PROG_ERROR, + } + match current_block_100 { + 4166486009154926805 => { + if *in_pos >= in_size { + return LZMA_OK; + } + if (*coder).pos == 0 { + if *in_0.offset(*in_pos as isize) == INDEX_INDICATOR { + (*coder).sequence = SEQ_INDEX; + current_block_100 = 16789764818708874114; + } else { + (*coder).block_options.header_size = + ((*in_0.offset(*in_pos as isize) as u32) + 1) * 4; + current_block_100 = 13242334135786603907; + } + } else { + current_block_100 = 13242334135786603907; + } + match current_block_100 { + 16789764818708874114 => {} + _ => { + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + (*coder).block_options.header_size as size_t, + ); + if (*coder).pos < (*coder).block_options.header_size as size_t { + return LZMA_OK; + } + (*coder).pos = 0; + (*coder).sequence = SEQ_BLOCK_INIT; + current_block_100 = 3500765272169221397; + } + } + } + 17861496924281778896 => { + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + LZMA_STREAM_HEADER_SIZE as size_t, + ); + if (*coder).pos < LZMA_STREAM_HEADER_SIZE as size_t { + return LZMA_OK; + } + (*coder).pos = 0; + let mut footer_flags: lzma_stream_flags = lzma_stream_flags { + version: 0, + backward_size: 0, + check: LZMA_CHECK_NONE, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_bool1: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + reserved_int1: 0, + reserved_int2: 0, + }; + let ret_3: lzma_ret = lzma_stream_footer_decode( + ::core::ptr::addr_of_mut!(footer_flags), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret_3 != LZMA_OK { + return if ret_3 == LZMA_FORMAT_ERROR { + LZMA_DATA_ERROR + } else { + ret_3 + }; + } + if lzma_index_hash_size((*coder).index_hash) != footer_flags.backward_size { + return LZMA_DATA_ERROR; + } + let ret__1: lzma_ret = lzma_stream_flags_compare( + ::core::ptr::addr_of_mut!((*coder).stream_flags), + ::core::ptr::addr_of_mut!(footer_flags), + ); + if ret__1 != LZMA_OK { + return ret__1; + } + if !(*coder).concatenated { + return LZMA_STREAM_END; + } + (*coder).sequence = SEQ_STREAM_PADDING; + current_block_100 = 15462640364611497761; + } + _ => {} + } + match current_block_100 { + 15462640364611497761 => { + loop { + if *in_pos >= in_size { + if action != LZMA_FINISH { + return LZMA_OK; + } + return if (*coder).pos == 0 { + LZMA_STREAM_END + } else { + LZMA_DATA_ERROR + }; + } + if *in_0.offset(*in_pos as isize) != 0 { + break; + } + *in_pos += 1; + (*coder).pos = ((*coder).pos + 1) & 3; + } + if (*coder).pos != 0 { + *in_pos += 1; + return LZMA_DATA_ERROR; + } + let ret__2: lzma_ret = stream_decoder_reset(coder, allocator); + if ret__2 != LZMA_OK { + return ret__2; + } + current_block_100 = 16789764818708874114; + } + 3500765272169221397 => { + (*coder).block_options.version = 1; + let mut filters: [lzma_filter; 5] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5]; + (*coder).block_options.filters = + ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter; + let ret_: lzma_ret = lzma_block_header_decode( + ::core::ptr::addr_of_mut!((*coder).block_options), + allocator, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).block_options.ignore_check = (*coder).ignore_check as lzma_bool; + let memusage: u64 = lzma_raw_decoder_memusage( + ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter + ) as u64; + let mut ret_0: lzma_ret = LZMA_OK; + if memusage == UINT64_MAX { + ret_0 = LZMA_OPTIONS_ERROR; + } else { + (*coder).memusage = memusage; + if memusage > (*coder).memlimit { + ret_0 = LZMA_MEMLIMIT_ERROR; + } else { + ret_0 = lzma_block_decoder_init( + ::core::ptr::addr_of_mut!((*coder).block_decoder), + allocator, + ::core::ptr::addr_of_mut!((*coder).block_options), + ); + } + } + lzma_filters_free( + ::core::ptr::addr_of_mut!(filters) as *mut lzma_filter, + allocator, + ); + (*coder).block_options.filters = core::ptr::null_mut(); + if ret_0 != LZMA_OK { + return ret_0; + } + (*coder).sequence = SEQ_BLOCK_RUN; + current_block_100 = 721385680381463314; + } + _ => {} + } + match current_block_100 { + 721385680381463314 => { + let ret_1: lzma_ret = (*coder).block_decoder.code.unwrap()( + (*coder).block_decoder.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + if ret_1 != LZMA_STREAM_END { + return ret_1; + } + let ret__0: lzma_ret = lzma_index_hash_append( + (*coder).index_hash, + lzma_block_unpadded_size(::core::ptr::addr_of_mut!((*coder).block_options)), + (*coder).block_options.uncompressed_size, + ); + if ret__0 != LZMA_OK { + return ret__0; + } + (*coder).sequence = SEQ_BLOCK_HEADER; + } + _ => {} + } + } +} +unsafe extern "C" fn stream_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).block_decoder), allocator); + lzma_index_hash_end((*coder).index_hash, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +extern "C" fn stream_decoder_get_check(coder_ptr: *const c_void) -> lzma_check { + return unsafe { + let coder: *const lzma_stream_coder = coder_ptr as *const lzma_stream_coder; + (*coder).stream_flags.check + }; +} +unsafe extern "C" fn stream_decoder_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + *memusage = (*coder).memusage; + *old_memlimit = (*coder).memlimit; + if new_memlimit != 0 { + if new_memlimit < (*coder).memusage { + return LZMA_MEMLIMIT_ERROR; + } + (*coder).memlimit = new_memlimit; + } + LZMA_OK +} +pub unsafe extern "C" fn lzma_stream_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + memlimit: u64, + flags: u32, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn(*mut lzma_next_coder, *const lzma_allocator, u64, u32) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_stream_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u32, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn(*mut lzma_next_coder, *const lzma_allocator, u64, u32) -> lzma_ret, + >, + uintptr_t, + >(Some( + lzma_stream_decoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + u64, + u32, + ) -> lzma_ret, + )); + if flags & !(LZMA_SUPPORTED_FLAGS as u32) != 0 { + return LZMA_OPTIONS_ERROR; + } + let mut coder: *mut lzma_stream_coder = (*next).coder as *mut lzma_stream_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + stream_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + stream_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).get_check = + Some(stream_decoder_get_check as unsafe extern "C" fn(*const c_void) -> lzma_check); + (*next).memconfig = Some( + stream_decoder_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*coder).block_decoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).index_hash = core::ptr::null_mut(); + } + (*coder).memlimit = if 1 > memlimit { 1 } else { memlimit }; + (*coder).memusage = LZMA_MEMUSAGE_BASE; + (*coder).tell_no_check = flags & LZMA_TELL_NO_CHECK as u32 != 0; + (*coder).tell_unsupported_check = flags & LZMA_TELL_UNSUPPORTED_CHECK as u32 != 0; + (*coder).tell_any_check = flags & LZMA_TELL_ANY_CHECK as u32 != 0; + (*coder).ignore_check = flags & LZMA_IGNORE_CHECK as u32 != 0; + (*coder).concatenated = flags & LZMA_CONCATENATED as u32 != 0; + (*coder).first_stream = true; + stream_decoder_reset(coder, allocator) +} +pub unsafe fn lzma_stream_decoder(strm: *mut lzma_stream, memlimit: u64, flags: u32) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = lzma_stream_decoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + memlimit, + flags, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_decoder_mt.rs b/liblzma-rs/src/common/stream_decoder_mt.rs new file mode 100644 index 00000000..b4875254 --- /dev/null +++ b/liblzma-rs/src/common/stream_decoder_mt.rs @@ -0,0 +1,1573 @@ +use crate::common::outqueue::{ + lzma_outq_clear_cache, lzma_outq_clear_cache2, lzma_outq_enable_partial_output, +}; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_stream_coder { + pub sequence: stream_decoder_mt_seq, + pub block_decoder: lzma_next_coder, + pub block_options: lzma_block, + pub filters: [lzma_filter; 5], + pub stream_flags: lzma_stream_flags, + pub index_hash: *mut lzma_index_hash, + pub timeout: u32, + pub thread_error: lzma_ret, + pub pending_error: lzma_ret, + pub threads_max: u32, + pub threads_initialized: u32, + pub threads: *mut worker_thread, + pub threads_free: *mut worker_thread, + pub thr: *mut worker_thread, + pub outq: lzma_outq, + pub mutex: mythread_mutex, + pub cond: mythread_cond, + pub memlimit_threading: u64, + pub memlimit_stop: u64, + pub mem_direct_mode: u64, + pub mem_in_use: u64, + pub mem_cached: u64, + pub mem_next_filters: u64, + pub mem_next_in: u64, + pub mem_next_block: u64, + pub progress_in: u64, + pub progress_out: u64, + pub tell_no_check: bool, + pub tell_unsupported_check: bool, + pub tell_any_check: bool, + pub ignore_check: bool, + pub concatenated: bool, + pub fail_fast: bool, + pub first_stream: bool, + pub out_was_filled: bool, + pub pos: size_t, + pub buffer: [u8; LZMA_BLOCK_HEADER_SIZE_MAX as usize], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct worker_thread { + pub state: worker_state, + pub in_0: *mut u8, + pub in_size: size_t, + pub in_filled: size_t, + pub in_pos: size_t, + pub out_pos: size_t, + pub coder: *mut lzma_stream_coder, + pub allocator: *const lzma_allocator, + pub outbuf: *mut lzma_outbuf, + pub progress_in: size_t, + pub progress_out: size_t, + pub partial_update_enabled: bool, + pub partial_update_started: bool, + pub block_decoder: lzma_next_coder, + pub block_options: lzma_block, + pub mem_filters: u64, + pub next: *mut worker_thread, + pub mutex: mythread_mutex, + pub cond: mythread_cond, + pub thread_id: mythread, +} +pub const THR_EXIT: worker_state = 2; +pub type stream_decoder_mt_seq = c_uint; +pub const SEQ_ERROR: stream_decoder_mt_seq = 11; +pub const SEQ_STREAM_PADDING: stream_decoder_mt_seq = 10; +pub const SEQ_STREAM_FOOTER: stream_decoder_mt_seq = 9; +pub const SEQ_INDEX_DECODE: stream_decoder_mt_seq = 8; +pub const SEQ_INDEX_WAIT_OUTPUT: stream_decoder_mt_seq = 7; +pub const SEQ_BLOCK_DIRECT_RUN: stream_decoder_mt_seq = 6; +pub const SEQ_BLOCK_DIRECT_INIT: stream_decoder_mt_seq = 5; +pub const SEQ_BLOCK_THR_RUN: stream_decoder_mt_seq = 4; +pub const SEQ_BLOCK_THR_INIT: stream_decoder_mt_seq = 3; +pub const SEQ_BLOCK_INIT: stream_decoder_mt_seq = 2; +pub const SEQ_BLOCK_HEADER: stream_decoder_mt_seq = 1; +pub const SEQ_STREAM_HEADER: stream_decoder_mt_seq = 0; +unsafe extern "C" fn worker_enable_partial_update(thr_ptr: *mut c_void) { + let thr: *mut worker_thread = thr_ptr as *mut worker_thread; + let mut mythread_i_325: c_uint = 0; + while if mythread_i_325 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_325: c_uint = 0; + while mythread_j_325 == 0 { + (*thr).partial_update_enabled = true; + mythread_cond_signal(::core::ptr::addr_of_mut!((*thr).cond)); + mythread_j_325 = 1; + } + mythread_i_325 = 1; + } +} +unsafe extern "C" fn worker_decoder(thr_ptr: *mut c_void) -> *mut c_void { + let thr: *mut worker_thread = thr_ptr as *mut worker_thread; + let mut in_filled: size_t = 0; + let mut partial_update_enabled: bool = false; + let mut ret: lzma_ret = LZMA_OK; + loop { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + loop { + if (*thr).state == THR_IDLE { + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*thr).cond), + ::core::ptr::addr_of_mut!((*thr).mutex), + ); + } else { + if (*thr).state == THR_EXIT { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + crate::alloc::internal_free((*thr).in_0 as *mut c_void, (*thr).allocator); + lzma_next_end( + ::core::ptr::addr_of_mut!((*thr).block_decoder), + (*thr).allocator, + ); + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*thr).mutex)); + mythread_cond_destroy(::core::ptr::addr_of_mut!((*thr).cond)); + return MYTHREAD_RET_VALUE; + } + (*thr).progress_in = (*thr).in_pos; + (*thr).progress_out = (*thr).out_pos; + in_filled = (*thr).in_filled; + partial_update_enabled = (*thr).partial_update_enabled; + if in_filled != (*thr).in_pos + || (partial_update_enabled && !(*thr).partial_update_started) + { + break; + } + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*thr).cond), + ::core::ptr::addr_of_mut!((*thr).mutex), + ); + } + } + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + let chunk_size: size_t = 16384; + if in_filled - (*thr).in_pos > chunk_size { + in_filled = (*thr).in_pos + chunk_size; + } + ret = (*thr).block_decoder.code.unwrap()( + (*thr).block_decoder.coder, + (*thr).allocator, + (*thr).in_0, + ::core::ptr::addr_of_mut!((*thr).in_pos), + in_filled, + ::core::ptr::addr_of_mut!((*(*thr).outbuf).buf) as *mut u8, + ::core::ptr::addr_of_mut!((*thr).out_pos), + (*(*thr).outbuf).allocated, + LZMA_RUN, + ); + if ret == LZMA_OK { + if partial_update_enabled { + (*thr).partial_update_started = true; + let mut mythread_i_415: c_uint = 0; + while if mythread_i_415 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_415: c_uint = 0; + while mythread_j_415 == 0 { + (*(*thr).outbuf).pos = (*thr).out_pos; + (*(*thr).outbuf).decoder_in_pos = (*thr).in_pos; + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*thr).coder).cond)); + mythread_j_415 = 1; + } + mythread_i_415 = 1; + } + } + } else { + let mut mythread_i_434: c_uint = 0; + while if mythread_i_434 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_434: c_uint = 0; + while mythread_j_434 == 0 { + if ret == LZMA_STREAM_END && (*thr).in_filled != (*thr).in_size { + ret = LZMA_PROG_ERROR; + } + if (*thr).state != THR_EXIT { + (*thr).state = THR_IDLE; + } + mythread_j_434 = 1; + } + mythread_i_434 = 1; + } + if ret == LZMA_STREAM_END { + crate::alloc::internal_free((*thr).in_0 as *mut c_void, (*thr).allocator); + (*thr).in_0 = core::ptr::null_mut(); + } + let mut mythread_i_458: c_uint = 0; + while if mythread_i_458 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_458: c_uint = 0; + while mythread_j_458 == 0 { + (*(*thr).coder).progress_in += (*thr).in_pos as u64; + (*(*thr).coder).progress_out += (*thr).out_pos as u64; + (*thr).progress_in = 0; + (*thr).progress_out = 0; + (*(*thr).outbuf).pos = (*thr).out_pos; + (*(*thr).outbuf).decoder_in_pos = (*thr).in_pos; + (*(*thr).outbuf).finished = true; + (*(*thr).outbuf).finish_ret = ret; + (*thr).outbuf = core::ptr::null_mut(); + if ret != LZMA_STREAM_END && (*(*thr).coder).thread_error == LZMA_OK { + (*(*thr).coder).thread_error = ret; + } + if ret == LZMA_STREAM_END { + (*(*thr).coder).mem_in_use -= (*thr).in_size as u64; + (*(*thr).coder).mem_in_use -= (*thr).mem_filters; + (*(*thr).coder).mem_cached += (*thr).mem_filters; + (*thr).next = (*(*thr).coder).threads_free; + (*(*thr).coder).threads_free = thr; + } + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*thr).coder).cond)); + mythread_j_458 = 1; + } + mythread_i_458 = 1; + } + } + } +} +unsafe fn threads_end(coder: *mut lzma_stream_coder, allocator: *const lzma_allocator) { + let mut i: u32 = 0; + while i < (*coder).threads_initialized { + let mut mythread_i_502: c_uint = 0; + while if mythread_i_502 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_502: c_uint = 0; + while mythread_j_502 == 0 { + (*(*coder).threads.offset(i as isize)).state = THR_EXIT; + mythread_cond_signal(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).cond + )); + mythread_j_502 = 1; + } + mythread_i_502 = 1; + } + i += 1; + } + let mut i_0: u32 = 0; + while i_0 < (*coder).threads_initialized { + mythread_join((*(*coder).threads.offset(i_0 as isize)).thread_id); + i_0 += 1; + } + crate::alloc::internal_free((*coder).threads as *mut c_void, allocator); + (*coder).threads_initialized = 0; + (*coder).threads = core::ptr::null_mut(); + (*coder).threads_free = core::ptr::null_mut(); + (*coder).mem_in_use = 0; + (*coder).mem_cached = 0; +} +unsafe fn threads_stop(coder: *mut lzma_stream_coder) { + let mut i: u32 = 0; + while i < (*coder).threads_initialized { + let mut mythread_i_538: c_uint = 0; + while if mythread_i_538 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_538: c_uint = 0; + while mythread_j_538 == 0 { + (*(*coder).threads.offset(i as isize)).state = THR_IDLE; + mythread_j_538 = 1; + } + mythread_i_538 = 1; + } + i += 1; + } +} +unsafe fn initialize_new_thread( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, +) -> lzma_ret { + if (*coder).threads.is_null() { + (*coder).threads = crate::alloc::internal_alloc_array::( + (*coder).threads_max as size_t, + allocator, + ); + if (*coder).threads.is_null() { + return LZMA_MEM_ERROR; + } + } + let thr: *mut worker_thread = (*coder) + .threads + .offset((*coder).threads_initialized as isize) + as *mut worker_thread; + if mythread_mutex_init(::core::ptr::addr_of_mut!((*thr).mutex)) == 0 { + if mythread_cond_init(::core::ptr::addr_of_mut!((*thr).cond)) == 0 { + (*thr).state = THR_IDLE; + (*thr).in_0 = core::ptr::null_mut(); + (*thr).in_size = 0; + (*thr).allocator = allocator; + (*thr).coder = coder as *mut lzma_stream_coder; + (*thr).outbuf = core::ptr::null_mut(); + (*thr).block_decoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*thr).mem_filters = 0; + if mythread_create( + ::core::ptr::addr_of_mut!((*thr).thread_id), + Some(worker_decoder as unsafe extern "C" fn(*mut c_void) -> *mut c_void), + thr as *mut c_void, + ) != 0 + { + mythread_cond_destroy(::core::ptr::addr_of_mut!((*thr).cond)); + } else { + (*coder).threads_initialized += 1; + (*coder).thr = thr; + return LZMA_OK; + } + } + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*thr).mutex)); + } + LZMA_MEM_ERROR +} +unsafe fn get_thread(coder: *mut lzma_stream_coder, allocator: *const lzma_allocator) -> lzma_ret { + let mut mythread_i_608: c_uint = 0; + while if mythread_i_608 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_608: c_uint = 0; + while mythread_j_608 == 0 { + if !(*coder).threads_free.is_null() { + (*coder).thr = (*coder).threads_free; + (*coder).threads_free = (*(*coder).threads_free).next; + (*coder).mem_cached -= (*(*coder).thr).mem_filters; + } + mythread_j_608 = 1; + } + mythread_i_608 = 1; + } + if (*coder).thr.is_null() { + let ret_: lzma_ret = initialize_new_thread(coder, allocator); + if ret_ != LZMA_OK { + return ret_; + } + } + (*(*coder).thr).in_filled = 0; + (*(*coder).thr).in_pos = 0; + (*(*coder).thr).out_pos = 0; + (*(*coder).thr).progress_in = 0; + (*(*coder).thr).progress_out = 0; + (*(*coder).thr).partial_update_enabled = false; + (*(*coder).thr).partial_update_started = false; + LZMA_OK +} +unsafe fn read_output_and_wait( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + input_is_possible: *mut bool, + waiting_allowed: bool, + wait_abs: *mut mythread_condtime, + has_blocked: *mut bool, +) -> lzma_ret { + let mut ret: lzma_ret = LZMA_OK; + let mut mythread_i_654: c_uint = 0; + while if mythread_i_654 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_654: c_uint = 0; + while mythread_j_654 == 0 { + loop { + let out_start: size_t = *out_pos; + loop { + ret = lzma_outq_read( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + core::ptr::null_mut(), + ); + if ret == LZMA_STREAM_END { + lzma_outq_enable_partial_output( + ::core::ptr::addr_of_mut!((*coder).outq), + Some( + worker_enable_partial_update + as unsafe extern "C" fn(*mut c_void) -> (), + ), + ); + } + if ret != LZMA_STREAM_END { + break; + } + } + if ret != LZMA_OK { + break; + } + if *out_pos == out_size && *out_pos != out_start { + (*coder).out_was_filled = true; + } + if (*coder).thread_error != LZMA_OK { + if (*coder).fail_fast { + ret = (*coder).thread_error; + break; + } else { + (*coder).pending_error = LZMA_PROG_ERROR; + } + } + if !input_is_possible.is_null() + && (*coder).memlimit_threading - (*coder).mem_in_use - (*coder).outq.mem_in_use + >= (*coder).mem_next_block + && lzma_outq_has_buf(::core::ptr::addr_of_mut!((*coder).outq)) + && ((*coder).threads_initialized < (*coder).threads_max + || !(*coder).threads_free.is_null()) + { + *input_is_possible = true; + break; + } else { + if !waiting_allowed { + break; + } + if lzma_outq_is_empty(::core::ptr::addr_of_mut!((*coder).outq)) { + break; + } + if lzma_outq_is_readable(::core::ptr::addr_of_mut!((*coder).outq)) { + break; + } + if !(*coder).thr.is_null() && (*(*coder).thr).partial_update_enabled { + if (*(*(*coder).thr).outbuf).decoder_in_pos == (*(*coder).thr).in_filled { + break; + } + } + if (*coder).timeout != 0 { + if !*has_blocked { + *has_blocked = true; + mythread_condtime_set( + wait_abs, + ::core::ptr::addr_of_mut!((*coder).cond), + (*coder).timeout, + ); + } + if mythread_cond_timedwait( + ::core::ptr::addr_of_mut!((*coder).cond), + ::core::ptr::addr_of_mut!((*coder).mutex), + wait_abs, + ) != 0 + { + ret = LZMA_RET_INTERNAL1; + break; + } + } else { + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*coder).cond), + ::core::ptr::addr_of_mut!((*coder).mutex), + ); + } + if ret != LZMA_OK { + break; + } + } + } + mythread_j_654 = 1; + } + mythread_i_654 = 1; + } + if ret != LZMA_OK && ret != LZMA_RET_INTERNAL1 { + threads_stop(coder); + } + ret +} +unsafe fn decode_block_header( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + if *in_pos >= in_size { + return LZMA_OK; + } + if (*coder).pos == 0 { + if *in_0.offset(*in_pos as isize) == INDEX_INDICATOR { + return LZMA_RET_INTERNAL2; + } + (*coder).block_options.header_size = ((*in_0.offset(*in_pos as isize) as u32) + 1) * 4; + } + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + (*coder).block_options.header_size as size_t, + ); + if (*coder).pos < (*coder).block_options.header_size as size_t { + return LZMA_OK; + } + (*coder).pos = 0; + (*coder).block_options.version = 1; + (*coder).block_options.filters = + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter; + let ret_: lzma_ret = lzma_block_header_decode( + ::core::ptr::addr_of_mut!((*coder).block_options), + allocator, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).block_options.ignore_check = (*coder).ignore_check as lzma_bool; + LZMA_STREAM_END +} +extern "C" fn comp_blk_size(coder: *const lzma_stream_coder) -> size_t { + unsafe { + (vli_ceil4((*coder).block_options.compressed_size) + + lzma_check_size((*coder).stream_flags.check) as lzma_vli) as size_t + } +} +extern "C" fn is_direct_mode_needed(size: lzma_vli) -> bool { + size == LZMA_VLI_UNKNOWN || size > SIZE_MAX.wrapping_div(3 as c_ulong) as lzma_vli +} +unsafe fn stream_decoder_reset( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, +) -> lzma_ret { + (*coder).index_hash = lzma_index_hash_init((*coder).index_hash, allocator); + if (*coder).index_hash.is_null() { + return LZMA_MEM_ERROR; + } + (*coder).sequence = SEQ_STREAM_HEADER; + (*coder).pos = 0; + LZMA_OK +} + +#[inline(never)] +unsafe fn stream_decode_mt_block_init( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + wait_abs: *mut mythread_condtime, + has_blocked: *mut bool, +) -> Option { + if (*coder).mem_next_filters > (*coder).memlimit_stop { + let ret: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + true, + wait_abs, + has_blocked, + ); + if ret != LZMA_OK { + return Some(ret); + } + if !lzma_outq_is_empty(::core::ptr::addr_of_mut!((*coder).outq)) { + return Some(LZMA_OK); + } + return Some(LZMA_MEMLIMIT_ERROR); + } + if is_direct_mode_needed((*coder).block_options.compressed_size) + || is_direct_mode_needed((*coder).block_options.uncompressed_size) + { + (*coder).sequence = SEQ_BLOCK_DIRECT_INIT; + return None; + } + (*coder).mem_next_in = comp_blk_size(coder) as u64; + let mem_buffers: u64 = (*coder).mem_next_in + + lzma_outq_outbuf_memusage((*coder).block_options.uncompressed_size as size_t) as u64; + if (UINT64_MAX).wrapping_sub(mem_buffers) < (*coder).mem_next_filters { + (*coder).sequence = SEQ_BLOCK_DIRECT_INIT; + return None; + } + (*coder).mem_next_block = (*coder).mem_next_filters + mem_buffers; + if (*coder).mem_next_block > (*coder).memlimit_threading { + (*coder).sequence = SEQ_BLOCK_DIRECT_INIT; + return None; + } + lzma_next_end(::core::ptr::addr_of_mut!((*coder).block_decoder), allocator); + (*coder).mem_direct_mode = 0; + let ret: lzma_ret = lzma_index_hash_append( + (*coder).index_hash, + lzma_block_unpadded_size(::core::ptr::addr_of_mut!((*coder).block_options)), + (*coder).block_options.uncompressed_size, + ); + if ret != LZMA_OK { + (*coder).pending_error = ret; + (*coder).sequence = SEQ_ERROR; + return None; + } + (*coder).sequence = SEQ_BLOCK_THR_INIT; + None +} + +#[inline(never)] +unsafe fn stream_decode_mt_thread_init( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + wait_abs: *mut mythread_condtime, + has_blocked: *mut bool, +) -> Option { + let mut block_can_start: bool = false; + let ret: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + ::core::ptr::addr_of_mut!(block_can_start), + true, + wait_abs, + has_blocked, + ); + if ret != LZMA_OK { + return Some(ret); + } + if (*coder).pending_error != LZMA_OK { + (*coder).sequence = SEQ_ERROR; + return None; + } + if !block_can_start { + return Some(LZMA_OK); + } + let mut mem_in_use: u64 = 0; + let mut mem_cached: u64 = 0; + let mut thr: *mut worker_thread = core::ptr::null_mut(); + let mut mythread_i_1347: c_uint = 0; + while if mythread_i_1347 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_1347: c_uint = 0; + while mythread_j_1347 == 0 { + mem_in_use = (*coder).mem_in_use; + mem_cached = (*coder).mem_cached; + thr = (*coder).threads_free; + mythread_j_1347 = 1; + } + mythread_i_1347 = 1; + } + let mem_max: u64 = (*coder).memlimit_threading - (*coder).mem_next_block; + if mem_in_use + mem_cached + (*coder).outq.mem_allocated > mem_max { + lzma_outq_clear_cache2( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + (*coder).block_options.uncompressed_size as size_t, + ); + } + let mut mem_freed: u64 = 0; + if !thr.is_null() && mem_in_use + mem_cached + (*coder).outq.mem_in_use > mem_max { + if (*thr).mem_filters <= (*coder).mem_next_filters { + thr = (*thr).next; + } + while !thr.is_null() { + lzma_next_end(::core::ptr::addr_of_mut!((*thr).block_decoder), allocator); + mem_freed += (*thr).mem_filters; + (*thr).mem_filters = 0; + thr = (*thr).next; + } + } + let mut mythread_i_1410: c_uint = 0; + while if mythread_i_1410 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_1410: c_uint = 0; + while mythread_j_1410 == 0 { + (*coder).mem_cached -= mem_freed; + (*coder).mem_in_use += (*coder).mem_next_in + (*coder).mem_next_filters; + mythread_j_1410 = 1; + } + mythread_i_1410 = 1; + } + let mut ret: lzma_ret = lzma_outq_prealloc_buf( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + (*coder).block_options.uncompressed_size as size_t, + ); + if ret != LZMA_OK { + threads_stop(coder); + return Some(ret); + } + ret = get_thread(coder, allocator); + if ret != LZMA_OK { + threads_stop(coder); + return Some(ret); + } + (*(*coder).thr).mem_filters = (*coder).mem_next_filters; + (*(*coder).thr).block_options = (*coder).block_options; + ret = lzma_block_decoder_init( + ::core::ptr::addr_of_mut!((*(*coder).thr).block_decoder), + allocator, + ::core::ptr::addr_of_mut!((*(*coder).thr).block_options), + ); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + (*(*coder).thr).block_options.filters = core::ptr::null_mut(); + if ret != LZMA_OK { + (*coder).pending_error = ret; + (*coder).sequence = SEQ_ERROR; + return None; + } + (*(*coder).thr).in_size = (*coder).mem_next_in as size_t; + (*(*coder).thr).in_0 = + crate::alloc::internal_alloc_bytes((*(*coder).thr).in_size, allocator) as *mut u8; + if (*(*coder).thr).in_0.is_null() { + threads_stop(coder); + return Some(LZMA_MEM_ERROR); + } + (*(*coder).thr).outbuf = lzma_outq_get_buf( + ::core::ptr::addr_of_mut!((*coder).outq), + (*coder).thr as *mut c_void, + ); + let mut mythread_i_1478: c_uint = 0; + while if mythread_i_1478 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_1478: c_uint = 0; + while mythread_j_1478 == 0 { + (*(*coder).thr).state = THR_RUN; + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*coder).thr).cond)); + mythread_j_1478 = 1; + } + mythread_i_1478 = 1; + } + let mut mythread_i_1486: c_uint = 0; + while if mythread_i_1486 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_1486: c_uint = 0; + while mythread_j_1486 == 0 { + lzma_outq_enable_partial_output( + ::core::ptr::addr_of_mut!((*coder).outq), + Some(worker_enable_partial_update as unsafe extern "C" fn(*mut c_void) -> ()), + ); + mythread_j_1486 = 1; + } + mythread_i_1486 = 1; + } + (*coder).sequence = SEQ_BLOCK_THR_RUN; + None +} + +unsafe extern "C" fn stream_decode_mt( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + let mut wait_abs: mythread_condtime = timespec { + tv_sec: 0, + tv_nsec: 0, + }; + let mut has_blocked: bool = false; + let waiting_allowed: bool = + action == LZMA_FINISH || *in_pos == in_size && !(*coder).out_was_filled; + (*coder).out_was_filled = false; + loop { + let mut current_block_239: u64; + match (*coder).sequence { + 0 => { + let in_old: size_t = *in_pos; + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + LZMA_STREAM_HEADER_SIZE as size_t, + ); + (*coder).progress_in += (*in_pos - in_old) as u64; + if (*coder).pos < LZMA_STREAM_HEADER_SIZE as size_t { + return LZMA_OK; + } + (*coder).pos = 0; + let ret: lzma_ret = lzma_stream_header_decode( + ::core::ptr::addr_of_mut!((*coder).stream_flags), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret != LZMA_OK { + return if ret == LZMA_FORMAT_ERROR && !(*coder).first_stream { + LZMA_DATA_ERROR + } else { + ret + }; + } + (*coder).first_stream = false; + (*coder).block_options.check = (*coder).stream_flags.check; + (*coder).sequence = SEQ_BLOCK_HEADER; + if (*coder).tell_no_check && (*coder).stream_flags.check == LZMA_CHECK_NONE { + return LZMA_NO_CHECK; + } + if (*coder).tell_unsupported_check + && lzma_check_is_supported((*coder).stream_flags.check) == 0 + { + return LZMA_UNSUPPORTED_CHECK; + } + if (*coder).tell_any_check { + return LZMA_GET_CHECK; + } + current_block_239 = 7149356873433890176; + } + 1 => { + current_block_239 = 7149356873433890176; + } + 2 => { + current_block_239 = 3123434771885419771; + } + 3 => { + current_block_239 = 11441799814184323368; + } + 4 => { + current_block_239 = 7728257318064351663; + } + 5 => { + let ret__3: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + true, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ); + if ret__3 != LZMA_OK { + return ret__3; + } + if !lzma_outq_is_empty(::core::ptr::addr_of_mut!((*coder).outq)) { + return LZMA_OK; + } + lzma_outq_clear_cache(::core::ptr::addr_of_mut!((*coder).outq), allocator); + threads_end(coder, allocator); + let ret_3: lzma_ret = lzma_block_decoder_init( + ::core::ptr::addr_of_mut!((*coder).block_decoder), + allocator, + ::core::ptr::addr_of_mut!((*coder).block_options), + ); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + (*coder).block_options.filters = core::ptr::null_mut(); + if ret_3 != LZMA_OK { + return ret_3; + } + (*coder).mem_direct_mode = (*coder).mem_next_filters; + (*coder).sequence = SEQ_BLOCK_DIRECT_RUN; + current_block_239 = 7173345243791314703; + } + 6 => { + current_block_239 = 7173345243791314703; + } + 7 => { + let ret__5: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + true, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ); + if ret__5 != LZMA_OK { + return ret__5; + } + if !lzma_outq_is_empty(::core::ptr::addr_of_mut!((*coder).outq)) { + return LZMA_OK; + } + (*coder).sequence = SEQ_INDEX_DECODE; + current_block_239 = 13812071707085482240; + } + 8 => { + current_block_239 = 13812071707085482240; + } + 9 => { + current_block_239 = 15174413556390356007; + } + 10 => { + current_block_239 = 17073193239823527980; + } + 11 => { + if !(*coder).fail_fast { + let ret__8: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + true, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ); + if ret__8 != LZMA_OK { + return ret__8; + } + if !lzma_outq_is_empty(::core::ptr::addr_of_mut!((*coder).outq)) { + return LZMA_OK; + } + } + return (*coder).pending_error; + } + _ => return LZMA_PROG_ERROR, + } + match current_block_239 { + 7173345243791314703 => { + let in_old_1: size_t = *in_pos; + let out_old: size_t = *out_pos; + let ret_4: lzma_ret = (*coder).block_decoder.code.unwrap()( + (*coder).block_decoder.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + (*coder).progress_in += (*in_pos - in_old_1) as u64; + (*coder).progress_out += (*out_pos - out_old) as u64; + if ret_4 != LZMA_STREAM_END { + return ret_4; + } + let ret__4: lzma_ret = lzma_index_hash_append( + (*coder).index_hash, + lzma_block_unpadded_size(::core::ptr::addr_of_mut!((*coder).block_options)), + (*coder).block_options.uncompressed_size, + ); + if ret__4 != LZMA_OK { + return ret__4; + } + (*coder).sequence = SEQ_BLOCK_HEADER; + current_block_239 = 11639917216603986996; + } + 7149356873433890176 => { + let in_old_0: size_t = *in_pos; + let ret_0: lzma_ret = decode_block_header(coder, allocator, in_0, in_pos, in_size); + (*coder).progress_in += (*in_pos - in_old_0) as u64; + if ret_0 == LZMA_OK { + if action == LZMA_FINISH && (*coder).fail_fast { + threads_stop(coder); + return LZMA_DATA_ERROR; + } + let ret_: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + waiting_allowed, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ); + if ret_ != LZMA_OK { + return ret_; + } + if (*coder).pending_error != LZMA_OK { + (*coder).sequence = SEQ_ERROR; + } else { + return LZMA_OK; + } + current_block_239 = 11639917216603986996; + } else if ret_0 == LZMA_RET_INTERNAL2 { + (*coder).sequence = SEQ_INDEX_WAIT_OUTPUT; + current_block_239 = 11639917216603986996; + } else if ret_0 != LZMA_STREAM_END { + (*coder).pending_error = ret_0; + (*coder).sequence = SEQ_ERROR; + current_block_239 = 11639917216603986996; + } else { + (*coder).mem_next_filters = lzma_raw_decoder_memusage( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + ); + if (*coder).mem_next_filters == UINT64_MAX { + (*coder).pending_error = LZMA_OPTIONS_ERROR; + (*coder).sequence = SEQ_ERROR; + current_block_239 = 11639917216603986996; + } else { + (*coder).sequence = SEQ_BLOCK_INIT; + current_block_239 = 3123434771885419771; + } + } + } + 13812071707085482240 => { + if *in_pos >= in_size { + return LZMA_OK; + } + let in_old_2: size_t = *in_pos; + let ret_5: lzma_ret = + lzma_index_hash_decode((*coder).index_hash, in_0, in_pos, in_size); + (*coder).progress_in += (*in_pos - in_old_2) as u64; + if ret_5 != LZMA_STREAM_END { + return ret_5; + } + (*coder).sequence = SEQ_STREAM_FOOTER; + current_block_239 = 15174413556390356007; + } + _ => {} + } + match current_block_239 { + 3123434771885419771 => { + if let Some(ret) = stream_decode_mt_block_init( + coder, + allocator, + out, + out_pos, + out_size, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ) { + return ret; + } + continue; + } + 15174413556390356007 => { + let in_old_3: size_t = *in_pos; + lzma_bufcpy( + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + LZMA_STREAM_HEADER_SIZE as size_t, + ); + (*coder).progress_in += (*in_pos - in_old_3) as u64; + if (*coder).pos < LZMA_STREAM_HEADER_SIZE as size_t { + return LZMA_OK; + } + (*coder).pos = 0; + let mut footer_flags: lzma_stream_flags = lzma_stream_flags { + version: 0, + backward_size: 0, + check: LZMA_CHECK_NONE, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_bool1: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + reserved_int1: 0, + reserved_int2: 0, + }; + let ret_6: lzma_ret = lzma_stream_footer_decode( + ::core::ptr::addr_of_mut!(footer_flags), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret_6 != LZMA_OK { + return if ret_6 == LZMA_FORMAT_ERROR { + LZMA_DATA_ERROR + } else { + ret_6 + }; + } + if lzma_index_hash_size((*coder).index_hash) != footer_flags.backward_size { + return LZMA_DATA_ERROR; + } + let ret__6: lzma_ret = lzma_stream_flags_compare( + ::core::ptr::addr_of_mut!((*coder).stream_flags), + ::core::ptr::addr_of_mut!(footer_flags), + ); + if ret__6 != LZMA_OK { + return ret__6; + } + if !(*coder).concatenated { + return LZMA_STREAM_END; + } + (*coder).sequence = SEQ_STREAM_PADDING; + current_block_239 = 17073193239823527980; + } + _ => {} + } + match current_block_239 { + 17073193239823527980 => { + loop { + if *in_pos >= in_size { + if action != LZMA_FINISH { + return LZMA_OK; + } + return if (*coder).pos == 0 { + LZMA_STREAM_END + } else { + LZMA_DATA_ERROR + }; + } + if *in_0.offset(*in_pos as isize) != 0 { + break; + } + *in_pos += 1; + (*coder).progress_in += 1; + (*coder).pos = ((*coder).pos + 1) & 3; + } + if (*coder).pos != 0 { + *in_pos += 1; + (*coder).progress_in += 1; + return LZMA_DATA_ERROR; + } + let ret__7: lzma_ret = stream_decoder_reset(coder, allocator); + if ret__7 != LZMA_OK { + return ret__7; + } + current_block_239 = 11639917216603986996; + } + 11441799814184323368 => { + if let Some(ret) = stream_decode_mt_thread_init( + coder, + allocator, + out, + out_pos, + out_size, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ) { + return ret; + } + continue; + } + _ => {} + } + match current_block_239 { + 7728257318064351663 => { + if action == LZMA_FINISH && (*coder).fail_fast { + let in_avail: size_t = in_size - *in_pos; + let in_needed: size_t = (*(*coder).thr).in_size - (*(*coder).thr).in_filled; + if in_avail < in_needed { + threads_stop(coder); + return LZMA_DATA_ERROR; + } + } + let mut cur_in_filled: size_t = (*(*coder).thr).in_filled; + lzma_bufcpy( + in_0, + in_pos, + in_size, + (*(*coder).thr).in_0, + ::core::ptr::addr_of_mut!(cur_in_filled), + (*(*coder).thr).in_size, + ); + let mut mythread_i_1517: c_uint = 0; + while if mythread_i_1517 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_1517: c_uint = 0; + while mythread_j_1517 == 0 { + (*(*coder).thr).in_filled = cur_in_filled; + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*coder).thr).cond)); + mythread_j_1517 = 1; + } + mythread_i_1517 = 1; + } + let ret__2: lzma_ret = read_output_and_wait( + coder, + allocator, + out, + out_pos, + out_size, + core::ptr::null_mut(), + waiting_allowed && *in_pos == in_size, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + ); + if ret__2 != LZMA_OK { + return ret__2; + } + if (*coder).pending_error != LZMA_OK { + (*coder).sequence = SEQ_ERROR; + } else { + if (*(*coder).thr).in_filled < (*(*coder).thr).in_size { + return LZMA_OK; + } + (*coder).thr = core::ptr::null_mut(); + (*coder).sequence = SEQ_BLOCK_HEADER; + } + } + _ => {} + } + } +} +unsafe extern "C" fn stream_decoder_mt_end( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, +) { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + threads_end(coder, allocator); + lzma_outq_end(::core::ptr::addr_of_mut!((*coder).outq), allocator); + lzma_next_end(::core::ptr::addr_of_mut!((*coder).block_decoder), allocator); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + lzma_index_hash_end((*coder).index_hash, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +extern "C" fn stream_decoder_mt_get_check(coder_ptr: *const c_void) -> lzma_check { + return unsafe { + let coder: *const lzma_stream_coder = coder_ptr as *const lzma_stream_coder; + (*coder).stream_flags.check + }; +} +unsafe extern "C" fn stream_decoder_mt_memconfig( + coder_ptr: *mut c_void, + memusage: *mut u64, + old_memlimit: *mut u64, + new_memlimit: u64, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + let mut mythread_i_1829: c_uint = 0; + while if mythread_i_1829 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_1829: c_uint = 0; + while mythread_j_1829 == 0 { + *memusage = (*coder).mem_direct_mode + + (*coder).mem_in_use + + (*coder).mem_cached + + (*coder).outq.mem_allocated; + mythread_j_1829 = 1; + } + mythread_i_1829 = 1; + } + if *memusage < LZMA_MEMUSAGE_BASE { + *memusage = LZMA_MEMUSAGE_BASE; + } + *old_memlimit = (*coder).memlimit_stop; + if new_memlimit != 0 { + if new_memlimit < *memusage { + return LZMA_MEMLIMIT_ERROR; + } + (*coder).memlimit_stop = new_memlimit; + } + LZMA_OK +} +unsafe extern "C" fn stream_decoder_mt_get_progress( + coder_ptr: *mut c_void, + progress_in: *mut u64, + progress_out: *mut u64, +) { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + let mut mythread_i_1862: c_uint = 0; + while if mythread_i_1862 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_1862: c_uint = 0; + while mythread_j_1862 == 0 { + *progress_in = (*coder).progress_in; + *progress_out = (*coder).progress_out; + let mut i: size_t = 0; + while i < (*coder).threads_initialized as size_t { + let mut mythread_i_1867: c_uint = 0; + while if mythread_i_1867 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_1867: c_uint = 0; + while mythread_j_1867 == 0 { + *progress_in += (*(*coder).threads.offset(i as isize)).progress_in as u64; + *progress_out += (*(*coder).threads.offset(i as isize)).progress_out as u64; + mythread_j_1867 = 1; + } + mythread_i_1867 = 1; + } + i += 1; + } + mythread_j_1862 = 1; + } + mythread_i_1862 = 1; + } +} +unsafe extern "C" fn stream_decoder_mt_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + options: *const lzma_mt, +) -> lzma_ret { + let mut coder: *mut lzma_stream_coder = core::ptr::null_mut(); + if (*options).threads == 0 || (*options).threads > LZMA_THREADS_MAX { + return LZMA_OPTIONS_ERROR; + } + if (*options).flags & !(LZMA_SUPPORTED_FLAGS as u32) != 0 { + return LZMA_OPTIONS_ERROR; + } + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + stream_decoder_mt_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + stream_decoder_mt_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + )); + coder = (*next).coder as *mut lzma_stream_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + if mythread_mutex_init(::core::ptr::addr_of_mut!((*coder).mutex)) != 0 { + crate::alloc::internal_free(coder as *mut c_void, allocator); + return LZMA_MEM_ERROR; + } + if mythread_cond_init(::core::ptr::addr_of_mut!((*coder).cond)) != 0 { + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*coder).mutex)); + crate::alloc::internal_free(coder as *mut c_void, allocator); + return LZMA_MEM_ERROR; + } + (*next).code = Some( + stream_decode_mt + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + stream_decoder_mt_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).get_check = + Some(stream_decoder_mt_get_check as unsafe extern "C" fn(*const c_void) -> lzma_check); + (*next).memconfig = Some( + stream_decoder_mt_memconfig + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64, u64) -> lzma_ret, + ); + (*next).get_progress = Some( + stream_decoder_mt_get_progress + as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64) -> (), + ); + (*coder).filters[0].id = LZMA_VLI_UNKNOWN; + core::ptr::write_bytes( + ::core::ptr::addr_of_mut!((*coder).outq) as *mut u8, + 0 as u8, + core::mem::size_of::(), + ); + (*coder).block_decoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).mem_direct_mode = 0; + (*coder).index_hash = core::ptr::null_mut(); + (*coder).threads = core::ptr::null_mut(); + (*coder).threads_free = core::ptr::null_mut(); + (*coder).threads_initialized = 0; + } + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + threads_end(coder, allocator); + (*coder).mem_in_use = 0; + (*coder).mem_cached = 0; + (*coder).mem_next_block = 0; + (*coder).progress_in = 0; + (*coder).progress_out = 0; + (*coder).sequence = SEQ_STREAM_HEADER; + (*coder).thread_error = LZMA_OK; + (*coder).pending_error = LZMA_OK; + (*coder).thr = core::ptr::null_mut(); + (*coder).timeout = (*options).timeout; + (*coder).memlimit_threading = if 1 > (*options).memlimit_threading { + 1 + } else { + (*options).memlimit_threading + }; + (*coder).memlimit_stop = if 1 > (*options).memlimit_stop { + 1 + } else { + (*options).memlimit_stop + }; + if (*coder).memlimit_threading > (*coder).memlimit_stop { + (*coder).memlimit_threading = (*coder).memlimit_stop; + } + (*coder).tell_no_check = (*options).flags & LZMA_TELL_NO_CHECK as u32 != 0; + (*coder).tell_unsupported_check = (*options).flags & LZMA_TELL_UNSUPPORTED_CHECK as u32 != 0; + (*coder).tell_any_check = (*options).flags & LZMA_TELL_ANY_CHECK as u32 != 0; + (*coder).ignore_check = (*options).flags & LZMA_IGNORE_CHECK as u32 != 0; + (*coder).concatenated = (*options).flags & LZMA_CONCATENATED as u32 != 0; + (*coder).fail_fast = (*options).flags & LZMA_FAIL_FAST as u32 != 0; + (*coder).first_stream = true; + (*coder).out_was_filled = false; + (*coder).pos = 0; + (*coder).threads_max = (*options).threads; + let ret_: lzma_ret = lzma_outq_init( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + (*coder).threads_max, + ); + if ret_ != LZMA_OK { + return ret_; + } + stream_decoder_reset(coder, allocator) +} +pub unsafe fn lzma_stream_decoder_mt(strm: *mut lzma_stream, options: *const lzma_mt) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = stream_decoder_mt_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + options, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_encoder.rs b/liblzma-rs/src/common/stream_encoder.rs new file mode 100644 index 00000000..42e03b76 --- /dev/null +++ b/liblzma-rs/src/common/stream_encoder.rs @@ -0,0 +1,443 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_stream_coder { + pub sequence: stream_encoder_seq, + pub block_encoder_is_initialized: bool, + pub block_encoder: lzma_next_coder, + pub block_options: lzma_block, + pub filters: [lzma_filter; 5], + pub index_encoder: lzma_next_coder, + pub index: *mut lzma_index, + pub buffer_pos: size_t, + pub buffer_size: size_t, + pub buffer: [u8; LZMA_BLOCK_HEADER_SIZE_MAX as usize], +} +pub type stream_encoder_seq = c_uint; +pub const SEQ_STREAM_FOOTER: stream_encoder_seq = 5; +pub const SEQ_INDEX_ENCODE: stream_encoder_seq = 4; +pub const SEQ_BLOCK_ENCODE: stream_encoder_seq = 3; +pub const SEQ_BLOCK_HEADER: stream_encoder_seq = 2; +pub const SEQ_BLOCK_INIT: stream_encoder_seq = 1; +pub const SEQ_STREAM_HEADER: stream_encoder_seq = 0; +unsafe fn block_encoder_init( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, +) -> lzma_ret { + (*coder).block_options.compressed_size = LZMA_VLI_UNKNOWN; + (*coder).block_options.uncompressed_size = LZMA_VLI_UNKNOWN; + let ret_: lzma_ret = lzma_block_header_size(::core::ptr::addr_of_mut!((*coder).block_options)); + if ret_ != LZMA_OK { + return ret_; + } + lzma_block_encoder_init( + ::core::ptr::addr_of_mut!((*coder).block_encoder), + allocator, + ::core::ptr::addr_of_mut!((*coder).block_options), + ) +} +unsafe extern "C" fn stream_encode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + while *out_pos < out_size { + match (*coder).sequence { + 0 | 2 | 5 => { + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).buffer_pos), + (*coder).buffer_size, + out, + out_pos, + out_size, + ); + if (*coder).buffer_pos < (*coder).buffer_size { + return LZMA_OK; + } + if (*coder).sequence == SEQ_STREAM_FOOTER { + return LZMA_STREAM_END; + } + (*coder).buffer_pos = 0; + (*coder).sequence += 1; + } + 1 => { + if *in_pos == in_size { + if action != LZMA_FINISH { + return if action == LZMA_RUN { + LZMA_OK + } else { + LZMA_STREAM_END + }; + } + let ret_: lzma_ret = lzma_index_encoder_init( + ::core::ptr::addr_of_mut!((*coder).index_encoder), + allocator, + (*coder).index, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).sequence = SEQ_INDEX_ENCODE; + } else { + if !(*coder).block_encoder_is_initialized { + let ret__0: lzma_ret = block_encoder_init(coder, allocator); + if ret__0 != LZMA_OK { + return ret__0; + } + } + (*coder).block_encoder_is_initialized = false; + if lzma_block_header_encode( + ::core::ptr::addr_of_mut!((*coder).block_options), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + (*coder).buffer_size = (*coder).block_options.header_size as size_t; + (*coder).sequence = SEQ_BLOCK_HEADER; + } + } + 3 => { + static CONVERT: [lzma_action; 5] = [ + LZMA_RUN, + LZMA_SYNC_FLUSH, + LZMA_FINISH, + LZMA_FINISH, + LZMA_FINISH, + ]; + let ret: lzma_ret = (*coder).block_encoder.code.unwrap()( + (*coder).block_encoder.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + CONVERT[action as usize], + ); + if ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH { + return ret; + } + let unpadded_size: lzma_vli = + lzma_block_unpadded_size(::core::ptr::addr_of_mut!((*coder).block_options)) + as lzma_vli; + let ret__1: lzma_ret = lzma_index_append( + (*coder).index, + allocator, + unpadded_size, + (*coder).block_options.uncompressed_size, + ); + if ret__1 != LZMA_OK { + return ret__1; + } + (*coder).sequence = SEQ_BLOCK_INIT; + } + 4 => { + let ret_0: lzma_ret = (*coder).index_encoder.code.unwrap()( + (*coder).index_encoder.coder, + allocator, + core::ptr::null(), + core::ptr::null_mut(), + 0, + out, + out_pos, + out_size, + LZMA_RUN, + ); + if ret_0 != LZMA_STREAM_END { + return ret_0; + } + let stream_flags: lzma_stream_flags = lzma_stream_flags { + version: 0, + backward_size: lzma_index_size((*coder).index), + check: (*coder).block_options.check, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_bool1: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + reserved_int1: 0, + reserved_int2: 0, + }; + if lzma_stream_footer_encode( + ::core::ptr::addr_of!(stream_flags), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + (*coder).buffer_size = LZMA_STREAM_HEADER_SIZE as size_t; + (*coder).sequence = SEQ_STREAM_FOOTER; + } + _ => return LZMA_PROG_ERROR, + } + } + LZMA_OK +} +unsafe extern "C" fn stream_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).block_encoder), allocator); + lzma_next_end(::core::ptr::addr_of_mut!((*coder).index_encoder), allocator); + lzma_index_end((*coder).index, allocator); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +#[inline(never)] +unsafe fn stream_encoder_update_before_block( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + temp_ptr: *mut lzma_filter, + filters_ptr: *mut lzma_filter, +) -> lzma_ret { + (*coder).block_encoder_is_initialized = false; + (*coder).block_options.filters = temp_ptr; + let ret = block_encoder_init(coder, allocator); + (*coder).block_options.filters = filters_ptr; + if ret != LZMA_OK { + return ret; + } + (*coder).block_encoder_is_initialized = true; + LZMA_OK +} + +#[inline(never)] +unsafe fn stream_encoder_update_mid_block( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + (*coder).block_encoder.update.unwrap()( + (*coder).block_encoder.coder, + allocator, + filters, + reversed_filters, + ) +} + +unsafe extern "C" fn stream_encoder_update( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + filters: *const lzma_filter, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + let mut temp: [lzma_filter; 5] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5]; + let temp_ptr = ::core::ptr::addr_of_mut!(temp) as *mut lzma_filter; + let filters_ptr = ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter; + let ret_: lzma_ret = lzma_filters_copy(filters, temp_ptr, allocator); + if ret_ != LZMA_OK { + return ret_; + } + let ret = if (*coder).sequence <= SEQ_BLOCK_INIT { + stream_encoder_update_before_block(coder, allocator, temp_ptr, filters_ptr) + } else if (*coder).sequence <= SEQ_BLOCK_ENCODE { + stream_encoder_update_mid_block(coder, allocator, filters, reversed_filters) + } else { + LZMA_PROG_ERROR + }; + if ret != LZMA_OK { + lzma_filters_free(temp_ptr, allocator); + return ret; + } + + lzma_filters_free(filters_ptr, allocator); + (*coder).filters = temp; + LZMA_OK +} +unsafe extern "C" fn stream_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter, + check: lzma_check, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter, + lzma_check, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + stream_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter, + lzma_check, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter, + lzma_check, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + stream_encoder_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter, + lzma_check, + ) -> lzma_ret, + )); + if filters.is_null() { + return LZMA_PROG_ERROR; + } + let mut coder: *mut lzma_stream_coder = (*next).coder as *mut lzma_stream_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + stream_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + stream_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).update = Some( + stream_encoder_update + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + ); + (*coder).filters[0].id = LZMA_VLI_UNKNOWN; + (*coder).block_encoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).index_encoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).index = core::ptr::null_mut(); + } + (*coder).sequence = SEQ_STREAM_HEADER; + (*coder).block_options.version = 0; + (*coder).block_options.check = check; + lzma_index_end((*coder).index, allocator); + (*coder).index = lzma_index_init(allocator); + if (*coder).index.is_null() { + return LZMA_MEM_ERROR; + } + let mut stream_flags: lzma_stream_flags = lzma_stream_flags { + version: 0, + backward_size: 0, + check: check, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_bool1: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + reserved_int1: 0, + reserved_int2: 0, + }; + let ret_: lzma_ret = lzma_stream_header_encode( + ::core::ptr::addr_of_mut!(stream_flags), + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).buffer_pos = 0; + (*coder).buffer_size = LZMA_STREAM_HEADER_SIZE as size_t; + stream_encoder_update(coder as *mut c_void, allocator, filters, core::ptr::null()) +} +pub unsafe fn lzma_stream_encoder( + strm: *mut lzma_stream, + filters: *const lzma_filter, + check: lzma_check, +) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = stream_encoder_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + filters, + check, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_SYNC_FLUSH as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FULL_FLUSH as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FULL_BARRIER as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_encoder_mt.rs b/liblzma-rs/src/common/stream_encoder_mt.rs new file mode 100644 index 00000000..dd919a16 --- /dev/null +++ b/liblzma-rs/src/common/stream_encoder_mt.rs @@ -0,0 +1,1412 @@ +use crate::common::block_buffer_encoder::{lzma_block_buffer_bound64, lzma_block_uncomp_encode}; +use crate::common::filter_encoder::lzma_mt_block_size; +use crate::common::outqueue::lzma_outq_memusage; +use crate::types::*; +pub type worker_thread = worker_thread_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct worker_thread_s { + pub state: worker_state, + pub in_0: *mut u8, + pub in_size: size_t, + pub outbuf: *mut lzma_outbuf, + pub coder: *mut lzma_stream_coder, + pub allocator: *const lzma_allocator, + pub progress_in: u64, + pub progress_out: u64, + pub block_encoder: lzma_next_coder, + pub block_options: lzma_block, + pub filters: [lzma_filter; 5], + pub next: *mut worker_thread, + pub mutex: mythread_mutex, + pub cond: mythread_cond, + pub thread_id: mythread, +} +pub type lzma_stream_coder = lzma_stream_coder_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_stream_coder_s { + pub sequence: stream_encoder_mt_seq, + pub block_size: size_t, + pub filters: [lzma_filter; 5], + pub filters_cache: [lzma_filter; 5], + pub index: *mut lzma_index, + pub index_encoder: lzma_next_coder, + pub stream_flags: lzma_stream_flags, + pub header: [u8; 12], + pub header_pos: size_t, + pub outq: lzma_outq, + pub outbuf_alloc_size: size_t, + pub timeout: u32, + pub thread_error: lzma_ret, + pub threads: *mut worker_thread, + pub threads_max: u32, + pub threads_initialized: u32, + pub threads_free: *mut worker_thread, + pub thr: *mut worker_thread, + pub progress_in: u64, + pub progress_out: u64, + pub mutex: mythread_mutex, + pub cond: mythread_cond, +} +pub type stream_encoder_mt_seq = c_uint; +pub const SEQ_STREAM_FOOTER: stream_encoder_mt_seq = 3; +pub const SEQ_INDEX: stream_encoder_mt_seq = 2; +pub const SEQ_BLOCK: stream_encoder_mt_seq = 1; +pub const SEQ_STREAM_HEADER: stream_encoder_mt_seq = 0; +pub const THR_EXIT: worker_state = 4; +pub const THR_STOP: worker_state = 3; +pub const THR_FINISH: worker_state = 2; +pub const BLOCK_SIZE_MAX: c_ulonglong = UINT64_MAX.wrapping_div(LZMA_THREADS_MAX as u64); +unsafe fn worker_error(thr: *mut worker_thread, ret: lzma_ret) { + let mut mythread_i_207: c_uint = 0; + while if mythread_i_207 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_207: c_uint = 0; + while mythread_j_207 == 0 { + if (*(*thr).coder).thread_error == LZMA_OK { + (*(*thr).coder).thread_error = ret; + } + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*thr).coder).cond)); + mythread_j_207 = 1; + } + mythread_i_207 = 1; + } +} +unsafe fn worker_encode( + thr: *mut worker_thread, + out_pos: *mut size_t, + mut state: worker_state, +) -> worker_state { + (*thr).block_options = lzma_block { + version: 0, + header_size: 0, + check: (*(*thr).coder).stream_flags.check, + compressed_size: (*(*thr).outbuf).allocated as lzma_vli, + uncompressed_size: (*(*thr).coder).block_size as lzma_vli, + filters: ::core::ptr::addr_of_mut!((*thr).filters) as *mut lzma_filter, + raw_check: [0; 64], + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + reserved_ptr3: core::ptr::null_mut(), + reserved_int1: 0, + reserved_int2: 0, + reserved_int3: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + ignore_check: 0, + reserved_bool2: 0, + reserved_bool3: 0, + reserved_bool4: 0, + reserved_bool5: 0, + reserved_bool6: 0, + reserved_bool7: 0, + reserved_bool8: 0, + }; + let mut ret: lzma_ret = lzma_block_header_size(::core::ptr::addr_of_mut!((*thr).block_options)); + if ret != LZMA_OK { + worker_error(thr, ret); + return THR_STOP; + } + ret = lzma_block_encoder_init( + ::core::ptr::addr_of_mut!((*thr).block_encoder), + (*thr).allocator, + ::core::ptr::addr_of_mut!((*thr).block_options), + ); + if ret != LZMA_OK { + worker_error(thr, ret); + return THR_STOP; + } + let mut in_pos: size_t = 0; + let mut in_size: size_t = 0; + *out_pos = (*thr).block_options.header_size as size_t; + let out_size: size_t = (*(*thr).outbuf).allocated; + loop { + let mut mythread_i_258: c_uint = 0; + while if mythread_i_258 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_258: c_uint = 0; + while mythread_j_258 == 0 { + (*thr).progress_in = in_pos as u64; + (*thr).progress_out = *out_pos as u64; + while in_size == (*thr).in_size && (*thr).state == THR_RUN { + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*thr).cond), + ::core::ptr::addr_of_mut!((*thr).mutex), + ); + } + state = (*thr).state; + in_size = (*thr).in_size; + mythread_j_258 = 1; + } + mythread_i_258 = 1; + } + if state >= THR_STOP { + return state; + } + let mut action: lzma_action = (if state == THR_FINISH { + LZMA_FINISH + } else { + LZMA_RUN + }) as lzma_action; + static mut in_chunk_max: size_t = 16384; + let mut in_limit: size_t = in_size; + if in_size - in_pos > in_chunk_max { + in_limit = in_pos + in_chunk_max; + action = LZMA_RUN; + } + ret = (*thr).block_encoder.code.unwrap()( + (*thr).block_encoder.coder, + (*thr).allocator, + (*thr).in_0, + ::core::ptr::addr_of_mut!(in_pos), + in_limit, + ::core::ptr::addr_of_mut!((*(*thr).outbuf).buf) as *mut u8, + out_pos, + out_size, + action, + ); + if ret != LZMA_OK || *out_pos >= out_size { + break; + } + } + match ret { + 1 => { + ret = lzma_block_header_encode( + ::core::ptr::addr_of_mut!((*thr).block_options), + ::core::ptr::addr_of_mut!((*(*thr).outbuf).buf) as *mut u8, + ); + if ret != LZMA_OK { + worker_error(thr, ret); + return THR_STOP; + } + } + 0 => { + let mut mythread_i_321: c_uint = 0; + while if mythread_i_321 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_321: c_uint = 0; + while mythread_j_321 == 0 { + while (*thr).state == THR_RUN { + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*thr).cond), + ::core::ptr::addr_of_mut!((*thr).mutex), + ); + } + state = (*thr).state; + in_size = (*thr).in_size; + mythread_j_321 = 1; + } + mythread_i_321 = 1; + } + if state >= THR_STOP { + return state; + } + *out_pos = 0; + ret = lzma_block_uncomp_encode( + ::core::ptr::addr_of_mut!((*thr).block_options), + (*thr).in_0, + in_size, + ::core::ptr::addr_of_mut!((*(*thr).outbuf).buf) as *mut u8, + out_pos, + out_size, + ); + if ret != LZMA_OK { + worker_error(thr, LZMA_PROG_ERROR); + return THR_STOP; + } + } + _ => { + worker_error(thr, ret); + return THR_STOP; + } + } + (*(*thr).outbuf).unpadded_size = + lzma_block_unpadded_size(::core::ptr::addr_of_mut!((*thr).block_options)); + (*(*thr).outbuf).uncompressed_size = (*thr).block_options.uncompressed_size; + THR_FINISH +} +unsafe extern "C" fn worker_start(thr_ptr: *mut c_void) -> *mut c_void { + let thr: *mut worker_thread = thr_ptr as *mut worker_thread; + let mut state: worker_state = THR_IDLE; + loop { + let mut mythread_i_370: c_uint = 0; + while if mythread_i_370 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_370: c_uint = 0; + while mythread_j_370 == 0 { + loop { + if (*thr).state == THR_STOP { + (*thr).state = THR_IDLE; + mythread_cond_signal(::core::ptr::addr_of_mut!((*thr).cond)); + } + state = (*thr).state; + if state != THR_IDLE { + break; + } + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*thr).cond), + ::core::ptr::addr_of_mut!((*thr).mutex), + ); + } + mythread_j_370 = 1; + } + mythread_i_370 = 1; + } + let mut out_pos: size_t = 0; + if state <= THR_FINISH { + state = worker_encode(thr, ::core::ptr::addr_of_mut!(out_pos), state); + } + if state == THR_EXIT { + break; + } + let mut mythread_i_401: c_uint = 0; + while if mythread_i_401 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_401: c_uint = 0; + while mythread_j_401 == 0 { + if (*thr).state != THR_EXIT { + (*thr).state = THR_IDLE; + mythread_cond_signal(::core::ptr::addr_of_mut!((*thr).cond)); + } + mythread_j_401 = 1; + } + mythread_i_401 = 1; + } + let mut mythread_i_408: c_uint = 0; + while if mythread_i_408 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*thr).coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_408: c_uint = 0; + while mythread_j_408 == 0 { + if state == THR_FINISH { + (*(*thr).outbuf).pos = out_pos; + (*(*thr).outbuf).finished = true; + } + (*(*thr).coder).progress_in += (*(*thr).outbuf).uncompressed_size as u64; + (*(*thr).coder).progress_out += out_pos as u64; + (*thr).progress_in = 0; + (*thr).progress_out = 0; + (*thr).next = (*(*thr).coder).threads_free; + (*(*thr).coder).threads_free = thr; + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*thr).coder).cond)); + mythread_j_408 = 1; + } + mythread_i_408 = 1; + } + } + lzma_filters_free( + ::core::ptr::addr_of_mut!((*thr).filters) as *mut lzma_filter, + (*thr).allocator, + ); + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*thr).mutex)); + mythread_cond_destroy(::core::ptr::addr_of_mut!((*thr).cond)); + lzma_next_end( + ::core::ptr::addr_of_mut!((*thr).block_encoder), + (*thr).allocator, + ); + crate::alloc::internal_free((*thr).in_0 as *mut c_void, (*thr).allocator); + MYTHREAD_RET_VALUE +} +unsafe fn threads_stop(coder: *mut lzma_stream_coder, wait_for_threads: bool) { + let mut i: u32 = 0; + while i < (*coder).threads_initialized { + let mut mythread_i_449: c_uint = 0; + while if mythread_i_449 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_449: c_uint = 0; + while mythread_j_449 == 0 { + (*(*coder).threads.offset(i as isize)).state = THR_STOP; + mythread_cond_signal(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).cond + )); + mythread_j_449 = 1; + } + mythread_i_449 = 1; + } + i += 1; + } + if !wait_for_threads { + return; + } + let mut i_0: u32 = 0; + while i_0 < (*coder).threads_initialized { + let mut mythread_i_460: c_uint = 0; + while if mythread_i_460 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i_0 as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i_0 as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_460: c_uint = 0; + while mythread_j_460 == 0 { + while (*(*coder).threads.offset(i_0 as isize)).state != THR_IDLE { + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*(*coder).threads.offset(i_0 as isize)).cond), + ::core::ptr::addr_of_mut!((*(*coder).threads.offset(i_0 as isize)).mutex), + ); + } + mythread_j_460 = 1; + } + mythread_i_460 = 1; + } + i_0 += 1; + } +} +unsafe fn threads_end(coder: *mut lzma_stream_coder, allocator: *const lzma_allocator) { + let mut i: u32 = 0; + while i < (*coder).threads_initialized { + let mut mythread_i_477: c_uint = 0; + while if mythread_i_477 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_477: c_uint = 0; + while mythread_j_477 == 0 { + (*(*coder).threads.offset(i as isize)).state = THR_EXIT; + mythread_cond_signal(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).cond + )); + mythread_j_477 = 1; + } + mythread_i_477 = 1; + } + i += 1; + } + let mut i_0: u32 = 0; + while i_0 < (*coder).threads_initialized { + let _ret: c_int = mythread_join((*(*coder).threads.offset(i_0 as isize)).thread_id); + i_0 += 1; + } + crate::alloc::internal_free((*coder).threads as *mut c_void, allocator); +} +unsafe fn initialize_new_thread( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, +) -> lzma_ret { + let thr: *mut worker_thread = (*coder) + .threads + .offset((*coder).threads_initialized as isize) + as *mut worker_thread; + (*thr).in_0 = crate::alloc::internal_alloc_bytes((*coder).block_size, allocator) as *mut u8; + if (*thr).in_0.is_null() { + return LZMA_MEM_ERROR; + } + if mythread_mutex_init(::core::ptr::addr_of_mut!((*thr).mutex)) == 0 { + if mythread_cond_init(::core::ptr::addr_of_mut!((*thr).cond)) == 0 { + (*thr).state = THR_IDLE; + (*thr).allocator = allocator; + (*thr).coder = coder; + (*thr).progress_in = 0; + (*thr).progress_out = 0; + (*thr).block_encoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*thr).filters[0].id = LZMA_VLI_UNKNOWN; + if mythread_create( + ::core::ptr::addr_of_mut!((*thr).thread_id), + Some(worker_start as unsafe extern "C" fn(*mut c_void) -> *mut c_void), + thr as *mut c_void, + ) != 0 + { + mythread_cond_destroy(::core::ptr::addr_of_mut!((*thr).cond)); + } else { + (*coder).threads_initialized += 1; + (*coder).thr = thr; + return LZMA_OK; + } + } + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*thr).mutex)); + } + crate::alloc::internal_free((*thr).in_0 as *mut c_void, allocator); + LZMA_MEM_ERROR +} +unsafe fn get_thread(coder: *mut lzma_stream_coder, allocator: *const lzma_allocator) -> lzma_ret { + if !lzma_outq_has_buf(::core::ptr::addr_of_mut!((*coder).outq)) { + return LZMA_OK; + } + let ret_: lzma_ret = lzma_outq_prealloc_buf( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + (*coder).outbuf_alloc_size, + ); + if ret_ != LZMA_OK { + return ret_; + } + if (*coder).filters_cache[0].id == LZMA_VLI_UNKNOWN { + let ret__0: lzma_ret = lzma_filters_copy( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + ::core::ptr::addr_of_mut!((*coder).filters_cache) as *mut lzma_filter, + allocator, + ); + if ret__0 != LZMA_OK { + return ret__0; + } + } + let mut mythread_i_560: c_uint = 0; + while if mythread_i_560 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_560: c_uint = 0; + while mythread_j_560 == 0 { + if !(*coder).threads_free.is_null() { + (*coder).thr = (*coder).threads_free; + (*coder).threads_free = (*(*coder).threads_free).next; + } + mythread_j_560 = 1; + } + mythread_i_560 = 1; + } + if (*coder).thr.is_null() { + if (*coder).threads_initialized == (*coder).threads_max { + return LZMA_OK; + } + let ret__1: lzma_ret = initialize_new_thread(coder, allocator); + if ret__1 != LZMA_OK { + return ret__1; + } + } + let mut mythread_i_578: c_uint = 0; + while if mythread_i_578 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_578: c_uint = 0; + while mythread_j_578 == 0 { + (*(*coder).thr).state = THR_RUN; + (*(*coder).thr).in_size = 0; + (*(*coder).thr).outbuf = lzma_outq_get_buf( + ::core::ptr::addr_of_mut!((*coder).outq), + core::ptr::null_mut(), + ); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*(*coder).thr).filters) as *mut lzma_filter, + allocator, + ); + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!((*coder).filters_cache) as *const u8, + ::core::ptr::addr_of_mut!((*(*coder).thr).filters) as *mut u8, + core::mem::size_of::<[lzma_filter; 5]>(), + ); + (*coder).filters_cache[0].id = LZMA_VLI_UNKNOWN; + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*coder).thr).cond)); + mythread_j_578 = 1; + } + mythread_i_578 = 1; + } + LZMA_OK +} +unsafe fn stream_encode_in( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + action: lzma_action, +) -> lzma_ret { + while *in_pos < in_size || !(*coder).thr.is_null() && action != LZMA_RUN { + if (*coder).thr.is_null() { + let ret: lzma_ret = get_thread(coder, allocator); + if (*coder).thr.is_null() { + return ret; + } + } + let mut thr_in_size: size_t = (*(*coder).thr).in_size; + lzma_bufcpy( + in_0, + in_pos, + in_size, + (*(*coder).thr).in_0, + ::core::ptr::addr_of_mut!(thr_in_size), + (*coder).block_size, + ); + let finish: bool = + thr_in_size == (*coder).block_size || *in_pos == in_size && action != LZMA_RUN; + let mut block_error: bool = false; + let mut mythread_i_628: c_uint = 0; + while if mythread_i_628 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*(*coder).thr).mutex)); + 1 + } != 0 + { + let mut mythread_j_628: c_uint = 0; + while mythread_j_628 == 0 { + if (*(*coder).thr).state == THR_IDLE { + block_error = true; + } else { + (*(*coder).thr).in_size = thr_in_size; + if finish { + (*(*coder).thr).state = THR_FINISH; + } + mythread_cond_signal(::core::ptr::addr_of_mut!((*(*coder).thr).cond)); + } + mythread_j_628 = 1; + } + mythread_i_628 = 1; + } + if block_error { + let mut ret_0: lzma_ret = LZMA_OK; + let mut mythread_i_649: c_uint = 0; + while if mythread_i_649 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_649: c_uint = 0; + while mythread_j_649 == 0 { + ret_0 = (*coder).thread_error; + mythread_j_649 = 1; + } + mythread_i_649 = 1; + } + return ret_0; + } + if finish { + (*coder).thr = core::ptr::null_mut(); + } + } + LZMA_OK +} +unsafe fn wait_for_work( + coder: *mut lzma_stream_coder, + wait_abs: *mut mythread_condtime, + has_blocked: *mut bool, + has_input: bool, +) -> bool { + if (*coder).timeout != 0 && !*has_blocked { + *has_blocked = true; + mythread_condtime_set( + wait_abs, + ::core::ptr::addr_of_mut!((*coder).cond), + (*coder).timeout, + ); + } + let mut timed_out: bool = false; + let mut mythread_i_689: c_uint = 0; + while if mythread_i_689 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_689: c_uint = 0; + while mythread_j_689 == 0 { + while (!has_input + || (*coder).threads_free.is_null() + || !lzma_outq_has_buf(::core::ptr::addr_of_mut!((*coder).outq))) + && !lzma_outq_is_readable(::core::ptr::addr_of_mut!((*coder).outq)) + && (*coder).thread_error == LZMA_OK + && !timed_out + { + if (*coder).timeout != 0 { + timed_out = mythread_cond_timedwait( + ::core::ptr::addr_of_mut!((*coder).cond), + ::core::ptr::addr_of_mut!((*coder).mutex), + wait_abs, + ) != 0; + } else { + mythread_cond_wait( + ::core::ptr::addr_of_mut!((*coder).cond), + ::core::ptr::addr_of_mut!((*coder).mutex), + ); + } + } + mythread_j_689 = 1; + } + mythread_i_689 = 1; + } + timed_out +} + +#[inline(never)] +unsafe fn stream_encode_mt_blocks( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let mut unpadded_size: lzma_vli = 0; + let mut uncompressed_size: lzma_vli = 0; + let mut ret: lzma_ret = LZMA_OK; + let mut has_blocked: bool = false; + let mut wait_abs: mythread_condtime = timespec { + tv_sec: 0 as __darwin_time_t, + tv_nsec: 0, + }; + loop { + let mut mythread_i_747: c_uint = 0; + while if mythread_i_747 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_747: c_uint = 0; + while mythread_j_747 == 0 { + ret = (*coder).thread_error; + if ret != LZMA_OK { + break; + } + ret = lzma_outq_read( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + out, + out_pos, + out_size, + ::core::ptr::addr_of_mut!(unpadded_size), + ::core::ptr::addr_of_mut!(uncompressed_size), + ); + mythread_j_747 = 1; + } + mythread_i_747 = 1; + } + if ret == LZMA_STREAM_END { + ret = lzma_index_append((*coder).index, allocator, unpadded_size, uncompressed_size); + if ret != LZMA_OK { + threads_stop(coder, false); + return ret; + } + if *out_pos < out_size { + continue; + } + } + if ret != LZMA_OK { + threads_stop(coder, false); + return ret; + } + ret = stream_encode_in(coder, allocator, in_0, in_pos, in_size, action); + if ret != LZMA_OK { + threads_stop(coder, false); + return ret; + } + if *in_pos == in_size { + if action == LZMA_RUN { + return LZMA_OK; + } + if action == LZMA_FULL_BARRIER { + return LZMA_STREAM_END; + } + if lzma_outq_is_empty(::core::ptr::addr_of_mut!((*coder).outq)) { + if action == LZMA_FINISH { + break; + } + if action == LZMA_FULL_FLUSH { + return LZMA_STREAM_END; + } + } + } + if *out_pos == out_size { + return LZMA_OK; + } + if wait_for_work( + coder, + ::core::ptr::addr_of_mut!(wait_abs), + ::core::ptr::addr_of_mut!(has_blocked), + *in_pos < in_size, + ) { + return LZMA_RET_INTERNAL1; + } + } + let ret_: lzma_ret = lzma_index_encoder_init( + ::core::ptr::addr_of_mut!((*coder).index_encoder), + allocator, + (*coder).index, + ); + if ret_ != LZMA_OK { + return ret_; + } + (*coder).sequence = SEQ_INDEX; + (*coder).progress_out += + (lzma_index_size((*coder).index) + LZMA_STREAM_HEADER_SIZE as lzma_vli) as u64; + LZMA_STREAM_END +} + +#[inline(never)] +unsafe fn stream_encode_mt_index( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + let ret: lzma_ret = (*coder).index_encoder.code.unwrap()( + (*coder).index_encoder.coder, + allocator, + core::ptr::null(), + core::ptr::null_mut(), + 0, + out, + out_pos, + out_size, + LZMA_RUN, + ); + if ret != LZMA_STREAM_END { + return ret; + } + (*coder).stream_flags.backward_size = lzma_index_size((*coder).index); + if lzma_stream_footer_encode( + ::core::ptr::addr_of_mut!((*coder).stream_flags), + ::core::ptr::addr_of_mut!((*coder).header) as *mut u8, + ) != LZMA_OK + { + return LZMA_PROG_ERROR; + } + (*coder).sequence = SEQ_STREAM_FOOTER; + LZMA_STREAM_END +} + +unsafe extern "C" fn stream_encode_mt( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + match (*coder).sequence { + SEQ_STREAM_HEADER => { + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).header) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).header_pos), + core::mem::size_of::<[u8; 12]>(), + out, + out_pos, + out_size, + ); + if (*coder).header_pos < core::mem::size_of::<[u8; 12]>() { + return LZMA_OK; + } + (*coder).header_pos = 0; + (*coder).sequence = SEQ_BLOCK; + } + SEQ_BLOCK | SEQ_INDEX | SEQ_STREAM_FOOTER => {} + _ => return LZMA_PROG_ERROR, + } + if (*coder).sequence == SEQ_BLOCK { + let ret: lzma_ret = stream_encode_mt_blocks( + coder, allocator, in_0, in_pos, in_size, out, out_pos, out_size, action, + ); + if ret != LZMA_STREAM_END { + return ret; + } + } + if (*coder).sequence == SEQ_INDEX { + let ret: lzma_ret = stream_encode_mt_index(coder, allocator, out, out_pos, out_size); + if ret != LZMA_STREAM_END { + return ret; + } + } + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).header) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).header_pos), + core::mem::size_of::<[u8; 12]>(), + out, + out_pos, + out_size, + ); + if (*coder).header_pos < core::mem::size_of::<[u8; 12]>() { + LZMA_OK + } else { + LZMA_STREAM_END + } +} +unsafe extern "C" fn stream_encoder_mt_end( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, +) { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + threads_end(coder, allocator); + lzma_outq_end(::core::ptr::addr_of_mut!((*coder).outq), allocator); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters_cache) as *mut lzma_filter, + allocator, + ); + lzma_next_end(::core::ptr::addr_of_mut!((*coder).index_encoder), allocator); + lzma_index_end((*coder).index, allocator); + mythread_cond_destroy(::core::ptr::addr_of_mut!((*coder).cond)); + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*coder).mutex)); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn stream_encoder_mt_update( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + filters: *const lzma_filter, + _reversed_filters: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + if (*coder).sequence > SEQ_BLOCK { + return LZMA_PROG_ERROR; + } + if !(*coder).thr.is_null() { + return LZMA_PROG_ERROR; + } + if lzma_raw_encoder_memusage(filters) == UINT64_MAX { + return LZMA_OPTIONS_ERROR; + } + let mut temp: [lzma_filter; 5] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5]; + let ret_: lzma_ret = lzma_filters_copy( + filters, + ::core::ptr::addr_of_mut!(temp) as *mut lzma_filter, + allocator, + ); + if ret_ != LZMA_OK { + return ret_; + } + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters_cache) as *mut lzma_filter, + allocator, + ); + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!(temp) as *const u8, + ::core::ptr::addr_of_mut!((*coder).filters) as *mut u8, + core::mem::size_of::<[lzma_filter; 5]>(), + ); + LZMA_OK +} +unsafe fn get_options( + options: *const lzma_mt, + opt_easy: *mut lzma_options_easy, + filters: *mut *const lzma_filter, + block_size: *mut u64, + outbuf_size_max: *mut u64, +) -> lzma_ret { + if options.is_null() { + return LZMA_PROG_ERROR; + } + if (*options).flags != 0 || (*options).threads == 0 || (*options).threads > LZMA_THREADS_MAX { + return LZMA_OPTIONS_ERROR; + } + if !(*options).filters.is_null() { + *filters = (*options).filters; + } else { + if lzma_easy_preset(opt_easy, (*options).preset) { + return LZMA_OPTIONS_ERROR; + } + *filters = ::core::ptr::addr_of_mut!((*opt_easy).filters) as *mut lzma_filter; + } + if (*options).block_size > 0 { + *block_size = (*options).block_size; + } else { + *block_size = lzma_mt_block_size(*filters); + } + if *block_size > BLOCK_SIZE_MAX as u64 || *block_size == UINT64_MAX { + return LZMA_OPTIONS_ERROR; + } + *outbuf_size_max = lzma_block_buffer_bound64(*block_size); + if *outbuf_size_max == 0 { + return LZMA_MEM_ERROR; + } + LZMA_OK +} +unsafe extern "C" fn get_progress( + coder_ptr: *mut c_void, + progress_in: *mut u64, + progress_out: *mut u64, +) { + let coder: *mut lzma_stream_coder = coder_ptr as *mut lzma_stream_coder; + let mut mythread_i_1010: c_uint = 0; + while if mythread_i_1010 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!((*coder).mutex)); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!((*coder).mutex)); + 1 + } != 0 + { + let mut mythread_j_1010: c_uint = 0; + while mythread_j_1010 == 0 { + *progress_in = (*coder).progress_in; + *progress_out = (*coder).progress_out; + let mut i: size_t = 0; + while i < (*coder).threads_initialized as size_t { + let mut mythread_i_1015: c_uint = 0; + while if mythread_i_1015 != 0 { + mythread_mutex_unlock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 0 + } else { + mythread_mutex_lock(::core::ptr::addr_of_mut!( + (*(*coder).threads.offset(i as isize)).mutex + )); + 1 + } != 0 + { + let mut mythread_j_1015: c_uint = 0; + while mythread_j_1015 == 0 { + *progress_in += (*(*coder).threads.offset(i as isize)).progress_in; + *progress_out += (*(*coder).threads.offset(i as isize)).progress_out; + mythread_j_1015 = 1; + } + mythread_i_1015 = 1; + } + i += 1; + } + mythread_j_1010 = 1; + } + mythread_i_1010 = 1; + } +} +#[inline(never)] +unsafe fn stream_encoder_mt_create_coder( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, +) -> *mut lzma_stream_coder { + let coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return core::ptr::null_mut(); + } + (*next).coder = coder as *mut c_void; + if mythread_mutex_init(::core::ptr::addr_of_mut!((*coder).mutex)) != 0 { + crate::alloc::internal_free(coder as *mut c_void, allocator); + (*next).coder = core::ptr::null_mut(); + return core::ptr::null_mut(); + } + if mythread_cond_init(::core::ptr::addr_of_mut!((*coder).cond)) != 0 { + mythread_mutex_destroy(::core::ptr::addr_of_mut!((*coder).mutex)); + crate::alloc::internal_free(coder as *mut c_void, allocator); + (*next).coder = core::ptr::null_mut(); + return core::ptr::null_mut(); + } + (*next).code = Some( + stream_encode_mt + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = + Some(stream_encoder_mt_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator)); + (*next).get_progress = + Some(get_progress as unsafe extern "C" fn(*mut c_void, *mut u64, *mut u64) -> ()); + (*next).update = Some( + stream_encoder_mt_update + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + ); + (*coder).filters[0].id = LZMA_VLI_UNKNOWN; + (*coder).filters_cache[0].id = LZMA_VLI_UNKNOWN; + (*coder).index_encoder = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).index = core::ptr::null_mut(); + core::ptr::write_bytes( + ::core::ptr::addr_of_mut!((*coder).outq) as *mut u8, + 0 as u8, + core::mem::size_of::(), + ); + (*coder).threads = core::ptr::null_mut(); + (*coder).threads_max = 0; + (*coder).threads_initialized = 0; + coder +} + +#[inline(never)] +unsafe fn stream_encoder_mt_prepare_threads( + coder: *mut lzma_stream_coder, + allocator: *const lzma_allocator, + threads: u32, +) -> lzma_ret { + if (*coder).threads_max != threads { + threads_end(coder, allocator); + (*coder).threads = core::ptr::null_mut(); + (*coder).threads_max = 0; + (*coder).threads_initialized = 0; + (*coder).threads_free = core::ptr::null_mut(); + (*coder).threads = + crate::alloc::internal_alloc_array::(threads as size_t, allocator); + if (*coder).threads.is_null() { + return LZMA_MEM_ERROR; + } + (*coder).threads_max = threads; + } else { + threads_stop(coder, true); + } + LZMA_OK +} + +unsafe extern "C" fn stream_encoder_mt_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + options: *const lzma_mt, +) -> lzma_ret { + if core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + stream_encoder_mt_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + )) != (*next).init + { + lzma_next_end(next, allocator); + } + (*next).init = core::mem::transmute::< + Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + >, + uintptr_t, + >(Some( + stream_encoder_mt_init + as unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_mt, + ) -> lzma_ret, + )); + let mut easy: lzma_options_easy = lzma_options_easy { + filters: [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5], + opt_lzma: lzma_options_lzma { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }, + }; + let mut filters: *const lzma_filter = core::ptr::null(); + let mut block_size: u64 = 0; + let mut outbuf_size_max: u64 = 0; + let ret_: lzma_ret = get_options( + options, + ::core::ptr::addr_of_mut!(easy), + ::core::ptr::addr_of_mut!(filters), + ::core::ptr::addr_of_mut!(block_size), + ::core::ptr::addr_of_mut!(outbuf_size_max), + ); + if ret_ != LZMA_OK { + return ret_; + } + if lzma_raw_encoder_memusage(filters) == UINT64_MAX { + return LZMA_OPTIONS_ERROR; + } + if (*options).check > LZMA_CHECK_ID_MAX { + return LZMA_PROG_ERROR; + } + if lzma_check_is_supported((*options).check) == 0 { + return LZMA_UNSUPPORTED_CHECK; + } + let mut coder: *mut lzma_stream_coder = (*next).coder as *mut lzma_stream_coder; + if coder.is_null() { + coder = stream_encoder_mt_create_coder(next, allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + } + (*coder).sequence = SEQ_STREAM_HEADER; + (*coder).block_size = block_size as size_t; + (*coder).outbuf_alloc_size = outbuf_size_max as size_t; + (*coder).thread_error = LZMA_OK; + (*coder).thr = core::ptr::null_mut(); + let ret__0: lzma_ret = stream_encoder_mt_prepare_threads(coder, allocator, (*options).threads); + if ret__0 != LZMA_OK { + return ret__0; + } + let ret__1: lzma_ret = lzma_outq_init( + ::core::ptr::addr_of_mut!((*coder).outq), + allocator, + (*options).threads, + ); + if ret__1 != LZMA_OK { + return ret__1; + } + (*coder).timeout = (*options).timeout; + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + lzma_filters_free( + ::core::ptr::addr_of_mut!((*coder).filters_cache) as *mut lzma_filter, + allocator, + ); + let ret__2: lzma_ret = lzma_filters_copy( + filters, + ::core::ptr::addr_of_mut!((*coder).filters) as *mut lzma_filter, + allocator, + ); + if ret__2 != LZMA_OK { + return ret__2; + } + lzma_index_end((*coder).index, allocator); + (*coder).index = lzma_index_init(allocator); + if (*coder).index.is_null() { + return LZMA_MEM_ERROR; + } + (*coder).stream_flags.version = 0; + (*coder).stream_flags.check = (*options).check; + let ret__3: lzma_ret = lzma_stream_header_encode( + ::core::ptr::addr_of_mut!((*coder).stream_flags), + ::core::ptr::addr_of_mut!((*coder).header) as *mut u8, + ); + if ret__3 != LZMA_OK { + return ret__3; + } + (*coder).header_pos = 0; + (*coder).progress_in = 0; + (*coder).progress_out = LZMA_STREAM_HEADER_SIZE as u64; + LZMA_OK +} +pub unsafe fn lzma_stream_encoder_mt(strm: *mut lzma_stream, options: *const lzma_mt) -> lzma_ret { + let ret_: lzma_ret = lzma_strm_init(strm); + if ret_ != LZMA_OK { + return ret_; + } + let ret__0: lzma_ret = stream_encoder_mt_init( + ::core::ptr::addr_of_mut!((*(*strm).internal).next), + (*strm).allocator, + options, + ); + if ret__0 != LZMA_OK { + lzma_end(strm); + return ret__0; + } + (*(*strm).internal).supported_actions[LZMA_RUN as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FULL_FLUSH as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FULL_BARRIER as usize] = true; + (*(*strm).internal).supported_actions[LZMA_FINISH as usize] = true; + LZMA_OK +} +pub unsafe fn lzma_stream_encoder_mt_memusage(options: *const lzma_mt) -> u64 { + let mut easy: lzma_options_easy = lzma_options_easy { + filters: [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5], + opt_lzma: lzma_options_lzma { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + lc: 0, + lp: 0, + pb: 0, + mode: 0, + nice_len: 0, + mf: 0, + depth: 0, + ext_flags: 0, + ext_size_low: 0, + ext_size_high: 0, + reserved_int4: 0, + reserved_int5: 0, + reserved_int6: 0, + reserved_int7: 0, + reserved_int8: 0, + reserved_enum1: LZMA_RESERVED_ENUM, + reserved_enum2: LZMA_RESERVED_ENUM, + reserved_enum3: LZMA_RESERVED_ENUM, + reserved_enum4: LZMA_RESERVED_ENUM, + reserved_ptr1: core::ptr::null_mut(), + reserved_ptr2: core::ptr::null_mut(), + }, + }; + let mut filters: *const lzma_filter = core::ptr::null(); + let mut block_size: u64 = 0; + let mut outbuf_size_max: u64 = 0; + if get_options( + options, + ::core::ptr::addr_of_mut!(easy), + ::core::ptr::addr_of_mut!(filters), + ::core::ptr::addr_of_mut!(block_size), + ::core::ptr::addr_of_mut!(outbuf_size_max), + ) != LZMA_OK + { + return UINT64_MAX; + } + let inbuf_memusage: u64 = ((*options).threads as u64).wrapping_mul(block_size); + let mut filters_memusage: u64 = lzma_raw_encoder_memusage(filters); + if filters_memusage == UINT64_MAX { + return UINT64_MAX; + } + filters_memusage = filters_memusage.wrapping_mul((*options).threads as u64); + let outq_memusage: u64 = lzma_outq_memusage(outbuf_size_max, (*options).threads) as u64; + if outq_memusage == UINT64_MAX { + return UINT64_MAX; + } + let mut total_memusage: u64 = (LZMA_MEMUSAGE_BASE) + .wrapping_add(core::mem::size_of::() as u64) + .wrapping_add( + ((*options).threads as usize).wrapping_mul(core::mem::size_of::()) + as u64, + ); + if (UINT64_MAX).wrapping_sub(total_memusage) < inbuf_memusage { + return UINT64_MAX; + } + total_memusage = total_memusage.wrapping_add(inbuf_memusage); + if (UINT64_MAX).wrapping_sub(total_memusage) < filters_memusage { + return UINT64_MAX; + } + total_memusage = total_memusage.wrapping_add(filters_memusage); + if (UINT64_MAX).wrapping_sub(total_memusage) < outq_memusage { + return UINT64_MAX; + } + total_memusage.wrapping_add(outq_memusage) +} diff --git a/liblzma-rs/src/common/stream_flags_common.rs b/liblzma-rs/src/common/stream_flags_common.rs new file mode 100644 index 00000000..be89bd00 --- /dev/null +++ b/liblzma-rs/src/common/stream_flags_common.rs @@ -0,0 +1,28 @@ +use crate::types::*; +pub static mut lzma_header_magic: [u8; 6] = [ + 0xfd as u8, 0x37 as u8, 0x7a as u8, 0x58 as u8, 0x5a as u8, 0, +]; +pub static mut lzma_footer_magic: [u8; 2] = [0x59 as u8, 0x5a as u8]; +pub unsafe fn lzma_stream_flags_compare( + a: *const lzma_stream_flags, + b: *const lzma_stream_flags, +) -> lzma_ret { + if (*a).version != 0 || (*b).version != 0 { + return LZMA_OPTIONS_ERROR; + } + if (*a).check > LZMA_CHECK_ID_MAX || (*b).check > LZMA_CHECK_ID_MAX { + return LZMA_PROG_ERROR; + } + if (*a).check != (*b).check { + return LZMA_DATA_ERROR; + } + if (*a).backward_size != LZMA_VLI_UNKNOWN && (*b).backward_size != LZMA_VLI_UNKNOWN { + if !is_backward_size_valid(a) || !is_backward_size_valid(b) { + return LZMA_PROG_ERROR; + } + if (*a).backward_size != (*b).backward_size { + return LZMA_DATA_ERROR; + } + } + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_flags_decoder.rs b/liblzma-rs/src/common/stream_flags_decoder.rs new file mode 100644 index 00000000..a43b6933 --- /dev/null +++ b/liblzma-rs/src/common/stream_flags_decoder.rs @@ -0,0 +1,78 @@ +use crate::common::stream_flags_common::{lzma_footer_magic, lzma_header_magic}; +use crate::types::*; +extern "C" fn stream_flags_decode(options: *mut lzma_stream_flags, in_0: *const u8) -> bool { + return unsafe { + if *in_0 != 0 || *in_0.offset(1) & 0xf0 != 0 { + return true; + } + (*options).version = 0; + (*options).check = (*in_0.offset(1) & 0xf) as lzma_check; + false + }; +} +pub unsafe fn lzma_stream_header_decode( + options: *mut lzma_stream_flags, + in_0: *const u8, +) -> lzma_ret { + if memcmp( + in_0 as *const c_void, + ::core::ptr::addr_of!(lzma_header_magic) as *const c_void, + core::mem::size_of::<[u8; 6]>(), + ) != 0 + { + return LZMA_FORMAT_ERROR; + } + let crc: u32 = lzma_crc32( + in_0.offset(core::mem::size_of::<[u8; 6]>() as isize), + LZMA_STREAM_FLAGS_SIZE as size_t, + 0, + ) as u32; + if crc + != read32le( + in_0.offset(core::mem::size_of::<[u8; 6]>() as isize) + .offset(LZMA_STREAM_FLAGS_SIZE as isize), + ) + { + return LZMA_DATA_ERROR; + } + if stream_flags_decode( + options, + in_0.offset(core::mem::size_of::<[u8; 6]>() as isize), + ) { + return LZMA_OPTIONS_ERROR; + } + (*options).backward_size = LZMA_VLI_UNKNOWN; + LZMA_OK +} +pub unsafe fn lzma_stream_footer_decode( + options: *mut lzma_stream_flags, + in_0: *const u8, +) -> lzma_ret { + if memcmp( + in_0.offset((core::mem::size_of::() * 2) as isize) + .offset(LZMA_STREAM_FLAGS_SIZE as isize) as *const c_void, + ::core::ptr::addr_of!(lzma_footer_magic) as *const c_void, + core::mem::size_of::<[u8; 2]>(), + ) != 0 + { + return LZMA_FORMAT_ERROR; + } + let crc: u32 = lzma_crc32( + in_0.offset(core::mem::size_of::() as isize), + core::mem::size_of::() + LZMA_STREAM_FLAGS_SIZE as size_t, + 0, + ) as u32; + if crc != read32le(in_0) { + return LZMA_DATA_ERROR; + } + if stream_flags_decode( + options, + in_0.offset((core::mem::size_of::() * 2) as isize), + ) { + return LZMA_OPTIONS_ERROR; + } + (*options).backward_size = + read32le(in_0.offset(core::mem::size_of::() as isize)) as lzma_vli; + (*options).backward_size = ((*options).backward_size + 1) * 4; + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_flags_encoder.rs b/liblzma-rs/src/common/stream_flags_encoder.rs new file mode 100644 index 00000000..c9695e31 --- /dev/null +++ b/liblzma-rs/src/common/stream_flags_encoder.rs @@ -0,0 +1,69 @@ +use crate::common::stream_flags_common::{lzma_footer_magic, lzma_header_magic}; +use crate::types::*; +extern "C" fn stream_flags_encode(options: *const lzma_stream_flags, out: *mut u8) -> bool { + return unsafe { + if (*options).check > LZMA_CHECK_ID_MAX { + return true; + } + *out = 0; + *out.offset(1) = (*options).check as u8; + false + }; +} +pub unsafe fn lzma_stream_header_encode( + options: *const lzma_stream_flags, + out: *mut u8, +) -> lzma_ret { + if (*options).version != 0 { + return LZMA_OPTIONS_ERROR; + } + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of!(lzma_header_magic) as *const u8, + out as *mut u8, + core::mem::size_of::<[u8; 6]>(), + ); + if stream_flags_encode( + options, + out.offset(core::mem::size_of::<[u8; 6]>() as isize), + ) { + return LZMA_PROG_ERROR; + } + let crc: u32 = lzma_crc32( + out.offset(core::mem::size_of::<[u8; 6]>() as isize), + LZMA_STREAM_FLAGS_SIZE as size_t, + 0, + ) as u32; + write32le( + out.offset(core::mem::size_of::<[u8; 6]>() as isize) + .offset(LZMA_STREAM_FLAGS_SIZE as isize), + crc, + ); + LZMA_OK +} +pub unsafe fn lzma_stream_footer_encode( + options: *const lzma_stream_flags, + out: *mut u8, +) -> lzma_ret { + if (*options).version != 0 { + return LZMA_OPTIONS_ERROR; + } + if !is_backward_size_valid(options) { + return LZMA_PROG_ERROR; + } + write32le( + out.offset(4), + (*options).backward_size.wrapping_div(4).wrapping_sub(1) as u32, + ); + if stream_flags_encode(options, out.offset((2 * 4) as isize)) { + return LZMA_PROG_ERROR; + } + let crc: u32 = lzma_crc32(out.offset(4), (4 + LZMA_STREAM_FLAGS_SIZE) as size_t, 0) as u32; + write32le(out, crc); + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of!(lzma_footer_magic) as *const u8, + out.offset((2 * 4) as isize) + .offset(LZMA_STREAM_FLAGS_SIZE as isize) as *mut u8, + core::mem::size_of::<[u8; 2]>(), + ); + LZMA_OK +} diff --git a/liblzma-rs/src/common/stream_mt.rs b/liblzma-rs/src/common/stream_mt.rs new file mode 100644 index 00000000..cd11ca6c --- /dev/null +++ b/liblzma-rs/src/common/stream_mt.rs @@ -0,0 +1,5 @@ +pub type lzma_mt = crate::types::lzma_mt; +pub use crate::common::stream_decoder_mt::lzma_stream_decoder_mt; +pub use crate::common::stream_encoder_mt::{ + lzma_stream_encoder_mt, lzma_stream_encoder_mt_memusage, +}; diff --git a/liblzma-rs/src/common/string_conversion.rs b/liblzma-rs/src/common/string_conversion.rs new file mode 100644 index 00000000..b78093f9 --- /dev/null +++ b/liblzma-rs/src/common/string_conversion.rs @@ -0,0 +1,1340 @@ +use crate::common::filter_common::lzma_validate_chain; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct filter_codec_def { + pub name: [c_char; 12], + pub opts_size: u32, + pub id: lzma_vli, + pub parse: Option< + unsafe extern "C" fn(*mut *const c_char, *const c_char, *mut c_void) -> *const c_char, + >, + pub optmap: *const option_map, + pub strfy_encoder: u8, + pub strfy_decoder: u8, + pub allow_null: bool, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct option_map { + pub name: [c_char; 12], + pub type_0: u8, + pub flags: u8, + pub offset: u16, + pub u: option_value, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union option_value { + pub map: *const name_value_map, + pub range: option_value_range, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct option_value_range { + pub min: u32, + pub max: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct name_value_map { + pub name: [c_char; 12], + pub value: u32, +} +pub const OPTMAP_TYPE_LZMA_MATCH_FINDER: option_type = 2; +pub const OPTMAP_TYPE_LZMA_MODE: option_type = 1; +pub const OPTMAP_TYPE_LZMA_PRESET: option_type = 3; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_str { + pub buf: *mut c_char, + pub pos: size_t, +} +pub type option_type = u8; +pub const OPTMAP_TYPE_UINT32: option_type = 0; +pub const INT_MAX: c_int = c_int::MAX; +pub const LZMA_STR_ALL_FILTERS: c_uint = 0x1; +pub const LZMA_STR_NO_VALIDATION: c_uint = 0x2; +pub const LZMA_STR_ENCODER: c_uint = 0x10; +pub const LZMA_STR_DECODER: c_uint = 0x20; +pub const LZMA_STR_GETOPT_LONG: c_uint = 0x40; +pub const LZMA_STR_NO_SPACES: c_uint = 0x80; +pub const LZMA_DICT_SIZE_DEFAULT: c_uint = 1u32 << 23; +pub const LZMA_LCLP_MIN: u32 = 0; +pub const LZMA_PB_MIN: u32 = 0; +pub const LZMA_PRESET_DEFAULT: c_uint = 6; +pub const STR_ALLOC_SIZE: u32 = 800; +unsafe fn str_init(str: *mut lzma_str, allocator: *const lzma_allocator) -> lzma_ret { + (*str).buf = lzma_alloc(STR_ALLOC_SIZE as size_t, allocator) as *mut c_char; + if (*str).buf.is_null() { + return LZMA_MEM_ERROR; + } + (*str).pos = 0; + LZMA_OK +} +unsafe fn str_free(str: *mut lzma_str, allocator: *const lzma_allocator) { + lzma_free((*str).buf as *mut c_void, allocator); +} +unsafe fn str_is_full(str: *const lzma_str) -> bool { + (*str).pos == (STR_ALLOC_SIZE - 1) as size_t +} +unsafe fn str_finish( + dest: *mut *mut c_char, + str: *mut lzma_str, + allocator: *const lzma_allocator, +) -> lzma_ret { + if str_is_full(str) { + lzma_free((*str).buf as *mut c_void, allocator); + *dest = core::ptr::null_mut(); + return LZMA_PROG_ERROR; + } + *(*str).buf.offset((*str).pos as isize) = '\0' as i32 as c_char; + *dest = (*str).buf; + LZMA_OK +} +unsafe fn str_append_str(str: *mut lzma_str, s: *const c_char) { + let len: size_t = strlen(s) as size_t; + let limit: size_t = (STR_ALLOC_SIZE - 1) as size_t - (*str).pos; + let copy_size: size_t = if len < limit { len } else { limit }; + core::ptr::copy_nonoverlapping( + s as *const u8, + (*str).buf.offset((*str).pos as isize) as *mut u8, + copy_size, + ); + (*str).pos += copy_size; +} +unsafe fn str_append_u32(str: *mut lzma_str, mut v: u32, use_byte_suffix: bool) { + if v == 0 { + str_append_str(str, crate::c_str!("0")); + } else { + static SUFFIXES: [[c_char; 4]; 4] = unsafe { + [ + core::mem::transmute::<[u8; 4], [c_char; 4]>(*b"\0\0\0\0"), + core::mem::transmute::<[u8; 4], [c_char; 4]>(*b"KiB\0"), + core::mem::transmute::<[u8; 4], [c_char; 4]>(*b"MiB\0"), + core::mem::transmute::<[u8; 4], [c_char; 4]>(*b"GiB\0"), + ] + }; + let mut suf: size_t = 0; + if use_byte_suffix { + while v & 1023 == 0 + && suf + < core::mem::size_of::<[[c_char; 4]; 4]>() / core::mem::size_of::<[c_char; 4]>() + - 1 + { + v >>= 10; + suf += 1; + } + } + let mut buf: [c_char; 16] = + core::mem::transmute::<[u8; 16], [c_char; 16]>(*b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); + let mut pos: size_t = core::mem::size_of::<[c_char; 16]>() - 1; + loop { + pos -= 1; + buf[pos as usize] = ('0' as i32 as u32 + v % 10) as c_char; + v /= 10; + if v == 0 { + break; + } + } + str_append_str( + str, + (::core::ptr::addr_of_mut!(buf) as *mut c_char).offset(pos as isize), + ); + str_append_str(str, SUFFIXES[suf as usize].as_ptr()); + }; +} +pub const NAME_LEN_MAX: u32 = 11; +pub const OPTMAP_USE_NAME_VALUE_MAP: u8 = 0x1; +pub const OPTMAP_USE_BYTE_SUFFIX: u8 = 0x2; +pub const OPTMAP_NO_STRFY_ZERO: u8 = 0x4; +static mut bcj_optmap: [option_map; 1] = unsafe { + [option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"start\0\0\0\0\0\0\0"), + type_0: 0, + flags: (OPTMAP_NO_STRFY_ZERO | OPTMAP_USE_BYTE_SUFFIX) as u8, + offset: 0, + u: option_value { + range: option_value_range { + min: 0, + max: UINT32_MAX, + }, + }, + }] +}; +extern "C" fn parse_bcj( + str: *mut *const c_char, + str_end: *const c_char, + filter_options: *mut c_void, +) -> *const c_char { + return unsafe { + parse_options( + str, + str_end, + filter_options, + ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + core::mem::size_of::<[option_map; 1]>() / core::mem::size_of::(), + ) + }; +} +static mut delta_optmap: [option_map; 1] = unsafe { + [option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"dist\0\0\0\0\0\0\0\0"), + type_0: 0, + flags: 0, + offset: 4, + u: option_value { + range: option_value_range { + min: LZMA_DELTA_DIST_MIN, + max: LZMA_DELTA_DIST_MAX, + }, + }, + }] +}; +extern "C" fn parse_delta( + str: *mut *const c_char, + str_end: *const c_char, + filter_options: *mut c_void, +) -> *const c_char { + return unsafe { + let opts: *mut lzma_options_delta = filter_options as *mut lzma_options_delta; + (*opts).type_0 = LZMA_DELTA_TYPE_BYTE; + (*opts).dist = LZMA_DELTA_DIST_MIN; + parse_options( + str, + str_end, + filter_options, + ::core::ptr::addr_of!(delta_optmap) as *const option_map, + (core::mem::size_of::<[option_map; 1]>()) + .wrapping_div(core::mem::size_of::()), + ) + }; +} +pub const LZMA12_PRESET_STR: [c_char; 7] = + unsafe { core::mem::transmute::<[u8; 7], [c_char; 7]>(*b"0-9[e]\0") }; +unsafe fn parse_lzma12_preset( + str: *mut *const c_char, + str_end: *const c_char, + preset: *mut u32, +) -> *const c_char { + if (**str as u8) < b'0' || (**str as u8) > b'9' { + return crate::c_str!("Unsupported preset"); + } + *preset = (**str as u8 - b'0') as u32; + loop { + *str = (*str).offset(1); + if *str >= str_end { + break; + } + match **str { + 101 => { + *preset = (*preset | LZMA_PRESET_EXTREME) as u32; + } + _ => { + return crate::c_str!("Unsupported flag in the preset"); + } + } + } + core::ptr::null() +} +unsafe fn set_lzma12_preset( + str: *mut *const c_char, + str_end: *const c_char, + filter_options: *mut c_void, +) -> *const c_char { + let mut preset: u32 = 0; + let errmsg: *const c_char = + parse_lzma12_preset(str, str_end, ::core::ptr::addr_of_mut!(preset)); + if !errmsg.is_null() { + return errmsg; + } + let opts: *mut lzma_options_lzma = filter_options as *mut lzma_options_lzma; + if lzma_lzma_preset(opts, preset) != 0 { + return crate::c_str!("Unsupported preset"); + } + core::ptr::null() +} +static lzma12_mode_map: [name_value_map; 3] = unsafe { + [ + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"fast\0\0\0\0\0\0\0\0"), + value: LZMA_MODE_FAST as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"normal\0\0\0\0\0\0"), + value: LZMA_MODE_NORMAL as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"\0\0\0\0\0\0\0\0\0\0\0\0"), + value: 0, + }, + ] +}; +static lzma12_mf_map: [name_value_map; 6] = unsafe { + [ + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"hc3\0\0\0\0\0\0\0\0\0"), + value: LZMA_MF_HC3 as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"hc4\0\0\0\0\0\0\0\0\0"), + value: LZMA_MF_HC4 as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"bt2\0\0\0\0\0\0\0\0\0"), + value: LZMA_MF_BT2 as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"bt3\0\0\0\0\0\0\0\0\0"), + value: LZMA_MF_BT3 as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"bt4\0\0\0\0\0\0\0\0\0"), + value: LZMA_MF_BT4 as u32, + }, + name_value_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"\0\0\0\0\0\0\0\0\0\0\0\0"), + value: 0, + }, + ] +}; +static mut lzma12_optmap: [option_map; 9] = [option_map { + name: [0; 12], + type_0: 0, + flags: 0, + offset: 0, + u: option_value { + map: core::ptr::null(), + }, +}; 9]; +unsafe extern "C" fn parse_lzma12( + str: *mut *const c_char, + str_end: *const c_char, + filter_options: *mut c_void, +) -> *const c_char { + let opts: *mut lzma_options_lzma = filter_options as *mut lzma_options_lzma; + let _preset_ret: bool = lzma_lzma_preset(opts, LZMA_PRESET_DEFAULT as u32) != 0; + let errmsg: *const c_char = parse_options( + str, + str_end, + filter_options, + ::core::ptr::addr_of!(lzma12_optmap) as *const option_map, + core::mem::size_of::<[option_map; 9]>() / core::mem::size_of::(), + ); + if !errmsg.is_null() { + return errmsg; + } + if (*opts).lc.wrapping_add((*opts).lp) > LZMA_LCLP_MAX { + return crate::c_str!("The sum of lc and lp must not exceed 4"); + } + core::ptr::null() +} +static mut filter_name_map: [filter_codec_def; 11] = unsafe { + [ + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"lzma1\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_LZMA1, + parse: Some( + parse_lzma12 + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(lzma12_optmap) as *const option_map, + strfy_encoder: 9, + strfy_decoder: 5, + allow_null: false, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"lzma2\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_LZMA2, + parse: Some( + parse_lzma12 + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(lzma12_optmap) as *const option_map, + strfy_encoder: 9, + strfy_decoder: 2, + allow_null: false, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"x86\0\0\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_X86, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"arm\0\0\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_ARM, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"armthumb\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_ARMTHUMB, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"arm64\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_ARM64, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"riscv\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_RISCV, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"powerpc\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_POWERPC, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"ia64\0\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_IA64, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"sparc\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_SPARC, + parse: Some( + parse_bcj + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(bcj_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: true, + }, + filter_codec_def { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"delta\0\0\0\0\0\0\0"), + opts_size: core::mem::size_of::() as u32, + id: LZMA_FILTER_DELTA, + parse: Some( + parse_delta + as unsafe extern "C" fn( + *mut *const c_char, + *const c_char, + *mut c_void, + ) -> *const c_char, + ), + optmap: ::core::ptr::addr_of!(delta_optmap) as *const option_map, + strfy_encoder: 1, + strfy_decoder: 1, + allow_null: false, + }, + ] +}; +unsafe fn parse_options( + str: *mut *const c_char, + str_end: *const c_char, + filter_options: *mut c_void, + optmap: *const option_map, + optmap_size: size_t, +) -> *const c_char { + while *str < str_end && **str != 0 { + if **str as u8 == b',' { + *str = (*str).offset(1); + } else { + let str_len: size_t = str_end.offset_from(*str) as size_t; + let mut name_eq_value_end: *const c_char = + memchr(*str as *const c_void, ',' as i32, str_len) as *const c_char; + if name_eq_value_end.is_null() { + name_eq_value_end = str_end; + } + let equals_sign: *const c_char = memchr( + *str as *const c_void, + '=' as i32, + name_eq_value_end.offset_from(*str) as size_t, + ) as *const c_char; + if equals_sign.is_null() || **str as u8 == b'=' { + return b"Options must be 'name=value' pairs separated with commas\0" as *const u8 + as *const c_char; + } + let name_len: size_t = equals_sign.offset_from(*str) as size_t; + if name_len > NAME_LEN_MAX as size_t { + return crate::c_str!("Unknown option name"); + } + let mut i: size_t = 0; + loop { + if i == optmap_size { + return crate::c_str!("Unknown option name"); + } + if memcmp( + *str as *const c_void, + ::core::ptr::addr_of!((*optmap.offset(i as isize)).name) as *const c_void, + name_len, + ) == 0 + && (*optmap.offset(i as isize)).name[name_len as usize] == 0 + { + break; + } + i += 1; + } + *str = equals_sign.offset(1); + let value_len: size_t = name_eq_value_end.offset_from(*str) as size_t; + if value_len == 0 { + return crate::c_str!("Option value cannot be empty"); + } + if (*optmap.offset(i as isize)).type_0 == OPTMAP_TYPE_LZMA_PRESET { + let errmsg: *const c_char = + set_lzma12_preset(str, name_eq_value_end, filter_options); + if !errmsg.is_null() { + return errmsg; + } + } else { + let mut v: u32 = 0; + if (*optmap.offset(i as isize)).flags & OPTMAP_USE_NAME_VALUE_MAP != 0 { + if value_len > NAME_LEN_MAX as size_t { + return crate::c_str!("Invalid option value"); + } + let map: *const name_value_map = (*optmap.offset(i as isize)).u.map; + let mut j: size_t = 0; + loop { + if (*map.offset(j as isize)).name[0] == 0 { + return crate::c_str!("Invalid option value"); + } + if memcmp( + *str as *const c_void, + ::core::ptr::addr_of!((*map.offset(j as isize)).name) as *const c_void, + value_len, + ) == 0 + && (*map.offset(j as isize)).name[value_len as usize] == 0 + { + v = (*map.offset(j as isize)).value; + break; + } else { + j += 1; + } + } + } else if (**str as u8) < b'0' || **str as u8 > b'9' { + return b"Value is not a non-negative decimal integer\0" as *const u8 + as *const c_char; + } else { + let mut p: *const c_char = *str; + v = 0; + loop { + if v > (UINT32_MAX).wrapping_div(10) { + return crate::c_str!("Value out of range"); + } + v = v.wrapping_mul(10); + let add: u32 = (*p as u8 - b'0') as u32; + if (UINT32_MAX).wrapping_sub(add) < v { + return crate::c_str!("Value out of range"); + } + v = v.wrapping_add(add); + p = p.offset(1); + if p >= name_eq_value_end || (*p as u8) < b'0' || (*p as u8) > b'9' { + break; + } + } + if p < name_eq_value_end { + let multiplier_start: *const c_char = p; + if (*optmap.offset(i as isize)).flags & OPTMAP_USE_BYTE_SUFFIX == 0 { + *str = multiplier_start; + return b"This option does not support any multiplier suffixes\0" + as *const u8 as *const c_char; + } + let mut shift: u32 = 0; + match *p { + 107 | 75 => { + shift = 10; + } + 109 | 77 => { + shift = 20; + } + 103 | 71 => { + shift = 30; + } + _ => { + *str = multiplier_start; + return b"Invalid multiplier suffix (KiB, MiB, or GiB)\0" + as *const u8 + as *const c_char; + } + } + p = p.offset(1); + if p < name_eq_value_end && *p as u8 == b'i' { + p = p.offset(1); + } + if p < name_eq_value_end && *p as u8 == b'B' { + p = p.offset(1); + } + if p < name_eq_value_end { + *str = multiplier_start; + return b"Invalid multiplier suffix (KiB, MiB, or GiB)\0" as *const u8 + as *const c_char; + } + if v > UINT32_MAX >> shift { + return crate::c_str!("Value out of range"); + } + v <<= shift; + } + if v < (*optmap.offset(i as isize)).u.range.min + || v > (*optmap.offset(i as isize)).u.range.max + { + return crate::c_str!("Value out of range"); + } + } + let ptr: *mut c_void = (filter_options as *mut c_char) + .offset((*optmap.offset(i as isize)).offset as isize) + as *mut c_void; + match (*optmap.offset(i as isize)).type_0 { + 1 => { + *(ptr as *mut lzma_mode) = v as lzma_mode; + } + 2 => { + *(ptr as *mut lzma_match_finder) = v as lzma_match_finder; + } + _ => { + *(ptr as *mut u32) = v; + } + } + *str = name_eq_value_end; + } + } + } + core::ptr::null() +} +unsafe fn parse_filter( + str: *mut *const c_char, + str_end: *const c_char, + filter: *mut lzma_filter, + allocator: *const lzma_allocator, + only_xz: bool, +) -> *const c_char { + let mut name_end: *const c_char = str_end; + let mut opts_start: *const c_char = str_end; + let mut p: *const c_char = *str; + while p < str_end { + if *p as u8 == b':' || *p as u8 == b'=' { + name_end = p; + opts_start = p.offset(1); + break; + } else { + p = p.offset(1); + } + } + let name_len: size_t = name_end.offset_from(*str) as size_t; + if name_len > NAME_LEN_MAX as size_t { + return crate::c_str!("Unknown filter name"); + } + let mut i: size_t = 0; + while i < core::mem::size_of::<[filter_codec_def; 11]>() + / core::mem::size_of::() + { + if memcmp( + *str as *const c_void, + ::core::ptr::addr_of!( + (*(::core::ptr::addr_of!(filter_name_map) as *const filter_codec_def) + .offset(i as isize)) + .name + ) as *const c_void, + name_len, + ) == 0 + && filter_name_map[i as usize].name[name_len as usize] == 0 + { + if only_xz && filter_name_map[i as usize].id >= LZMA_FILTER_RESERVED_START { + return b"This filter cannot be used in the .xz format\0" as *const u8 + as *const c_char; + } + let options: *mut c_void = + lzma_alloc_zero(filter_name_map[i as usize].opts_size as size_t, allocator); + if options.is_null() { + return crate::c_str!("Memory allocation failed"); + } + *str = opts_start; + let errmsg: *const c_char = + filter_name_map[i as usize].parse.unwrap()(str, str_end, options); + if !errmsg.is_null() { + lzma_free(options, allocator); + return errmsg; + } + (*filter).id = filter_name_map[i as usize].id; + (*filter).options = options; + return core::ptr::null(); + } + i += 1; + } + crate::c_str!("Unknown filter name") +} +unsafe fn str_to_filters( + str: *mut *const c_char, + filters: *mut lzma_filter, + flags: u32, + allocator: *const lzma_allocator, +) -> *const c_char { + let mut current_block: u64; + let mut errmsg: *const c_char = core::ptr::null(); + while **str as u8 == b' ' { + *str = (*str).offset(1); + } + if **str == 0 { + return b"Empty string is not allowed, try '6' if a default value is needed\0" as *const u8 + as *const c_char; + } + if **str as u8 >= b'0' && **str as u8 <= b'9' + || **str as u8 == b'-' + && (*(*str).offset(1) as u8 >= b'0' && *(*str).offset(1) as u8 <= b'9') + { + if **str as u8 == b'-' { + *str = (*str).offset(1); + } + let str_len: size_t = strlen(*str) as size_t; + let mut str_end: *const c_char = + memchr(*str as *const c_void, ' ' as i32, str_len) as *const c_char; + if !str_end.is_null() { + let mut i: size_t = 1; + while *str_end.offset(i as isize) != 0 { + if *str_end.offset(i as isize) as u8 != b' ' { + return crate::c_str!("Unsupported preset"); + } + i += 1; + } + } else { + str_end = (*str).offset(str_len as isize); + } + let mut preset: u32 = 0; + errmsg = parse_lzma12_preset(str, str_end, ::core::ptr::addr_of_mut!(preset)); + if !errmsg.is_null() { + return errmsg; + } + let opts: *mut lzma_options_lzma = + lzma_alloc(core::mem::size_of::(), allocator) + as *mut lzma_options_lzma; + if opts.is_null() { + return crate::c_str!("Memory allocation failed"); + } + if lzma_lzma_preset(opts, preset) != 0 { + lzma_free(opts as *mut c_void, allocator); + return crate::c_str!("Unsupported preset"); + } + (*filters).id = LZMA_FILTER_LZMA2; + (*filters).options = opts as *mut c_void; + (*filters.offset(1)).id = LZMA_VLI_UNKNOWN; + (*filters.offset(1)).options = core::ptr::null_mut(); + return core::ptr::null(); + } + let only_xz: bool = flags & LZMA_STR_ALL_FILTERS as u32 == 0; + let mut temp_filters: [lzma_filter; 5] = [lzma_filter { + id: 0, + options: core::ptr::null_mut(), + }; 5]; + let mut i_0: size_t = 0; + loop { + if i_0 == LZMA_FILTERS_MAX as size_t { + errmsg = crate::c_str!("The maximum number of filters is four"); + current_block = 6100283484465977373; + break; + } else { + if *(*str) as u8 == b'-' && *(*str).offset(1) as u8 == b'-' { + *str = (*str).offset(2); + } + let mut filter_end: *const c_char = *str; + while *filter_end != 0 { + if *filter_end as u8 == b'-' && *filter_end.offset(1) as u8 == b'-' + || *filter_end as u8 == b' ' + { + break; + } + filter_end = filter_end.offset(1); + } + if filter_end == *str { + errmsg = crate::c_str!("Filter name is missing"); + current_block = 6100283484465977373; + break; + } else { + errmsg = parse_filter( + str, + filter_end, + (::core::ptr::addr_of_mut!(temp_filters) as *mut lzma_filter) + .offset(i_0 as isize) as *mut lzma_filter, + allocator, + only_xz, + ); + if !errmsg.is_null() { + current_block = 6100283484465977373; + break; + } + while **str as u8 == b' ' { + *str = (*str).offset(1); + } + i_0 += 1; + if **str == 0 { + current_block = 15090052786889560393; + break; + } + } + } + } + match current_block { + 15090052786889560393 => { + temp_filters[i_0 as usize].id = LZMA_VLI_UNKNOWN; + temp_filters[i_0 as usize].options = core::ptr::null_mut(); + if flags & LZMA_STR_NO_VALIDATION as u32 == 0 { + let mut dummy: size_t = 0; + let ret: lzma_ret = lzma_validate_chain( + ::core::ptr::addr_of_mut!(temp_filters) as *mut lzma_filter, + ::core::ptr::addr_of_mut!(dummy), + ); + if ret != LZMA_OK { + errmsg = b"Invalid filter chain ('lzma2' missing at the end?)\0" as *const u8 + as *const c_char; + current_block = 6100283484465977373; + } else { + current_block = 12381812505308290051; + } + } else { + current_block = 12381812505308290051; + } + match current_block { + 6100283484465977373 => {} + _ => { + core::ptr::copy_nonoverlapping( + ::core::ptr::addr_of_mut!(temp_filters) as *const u8, + filters as *mut u8, + (i_0 + 1) * core::mem::size_of::(), + ); + return core::ptr::null(); + } + } + } + _ => {} + } + loop { + let old_i = i_0; + i_0 -= 1; + if old_i == 0 { + break; + } + lzma_free(temp_filters[i_0 as usize].options, allocator); + } + errmsg +} +pub unsafe fn lzma_str_to_filters( + str: *const c_char, + error_pos: *mut c_int, + filters: *mut lzma_filter, + flags: u32, + allocator: *const lzma_allocator, +) -> *const c_char { + if !error_pos.is_null() { + *error_pos = 0; + } + if str.is_null() || filters.is_null() { + return b"Unexpected core::ptr::null_mut() pointer argument(s) to lzma_str_to_filters()\0" + as *const u8 as *const c_char; + } + let supported_flags: u32 = LZMA_STR_ALL_FILTERS as u32 | LZMA_STR_NO_VALIDATION as u32; + if flags & !supported_flags != 0 { + return crate::c_str!("Unsupported flags to lzma_str_to_filters()"); + } + let mut used: *const c_char = str; + let errmsg: *const c_char = + str_to_filters(::core::ptr::addr_of_mut!(used), filters, flags, allocator); + if !error_pos.is_null() { + let n: size_t = used.offset_from(str) as size_t; + *error_pos = if n > INT_MAX as size_t { + INT_MAX + } else { + n as c_int + }; + } + errmsg +} +unsafe fn strfy_filter( + dest: *mut lzma_str, + mut delimiter: *const c_char, + optmap: *const option_map, + optmap_count: size_t, + filter_options: *const c_void, +) { + let mut i: size_t = 0; + while i < optmap_count { + if (*optmap.offset(i as isize)).type_0 != OPTMAP_TYPE_LZMA_PRESET { + let mut v: u32 = 0; + let ptr: *const c_void = (filter_options as *const c_char) + .offset((*optmap.offset(i as isize)).offset as isize) + as *const c_void; + match (*optmap.offset(i as isize)).type_0 { + 1 => { + v = *(ptr as *const lzma_mode) as u32; + } + 2 => { + v = *(ptr as *const lzma_match_finder) as u32; + } + _ => { + v = *(ptr as *const u32); + } + } + if v != 0 || (*optmap.offset(i as isize)).flags & OPTMAP_NO_STRFY_ZERO == 0 { + str_append_str(dest, delimiter); + delimiter = crate::c_str!(","); + str_append_str( + dest, + ::core::ptr::addr_of!((*optmap.offset(i as isize)).name) as *const c_char, + ); + str_append_str(dest, crate::c_str!("=")); + if (*optmap.offset(i as isize)).flags & OPTMAP_USE_NAME_VALUE_MAP != 0 { + let map: *const name_value_map = (*optmap.offset(i as isize)).u.map; + let mut j: size_t = 0; + loop { + if (*map.offset(j as isize)).name[0] == 0 { + str_append_str(dest, crate::c_str!("UNKNOWN")); + break; + } else if (*map.offset(j as isize)).value == v { + str_append_str( + dest, + ::core::ptr::addr_of!((*map.offset(j as isize)).name) + as *const c_char, + ); + break; + } else { + j += 1; + } + } + } else { + str_append_u32( + dest, + v, + (*optmap.offset(i as isize)).flags & OPTMAP_USE_BYTE_SUFFIX != 0, + ); + } + } + } + i += 1; + } +} +pub unsafe fn lzma_str_from_filters( + output_str: *mut *mut c_char, + filters: *const lzma_filter, + flags: u32, + allocator: *const lzma_allocator, +) -> lzma_ret { + if output_str.is_null() { + return LZMA_PROG_ERROR; + } + *output_str = core::ptr::null_mut(); + if filters.is_null() { + return LZMA_PROG_ERROR; + } + let supported_flags: u32 = LZMA_STR_ENCODER as u32 + | LZMA_STR_DECODER as u32 + | LZMA_STR_GETOPT_LONG as u32 + | LZMA_STR_NO_SPACES as u32; + if flags & !supported_flags != 0 { + return LZMA_OPTIONS_ERROR; + } + if (*filters).id == LZMA_VLI_UNKNOWN { + return LZMA_OPTIONS_ERROR; + } + let mut dest: lzma_str = lzma_str { + buf: core::ptr::null_mut(), + pos: 0, + }; + let ret_: lzma_ret = str_init(::core::ptr::addr_of_mut!(dest), allocator); + if ret_ != LZMA_OK { + return ret_; + } + let show_opts: bool = flags & (LZMA_STR_ENCODER as u32 | LZMA_STR_DECODER as u32) != 0; + let opt_delim: *const c_char = if flags & LZMA_STR_GETOPT_LONG as u32 != 0 { + crate::c_str!("=") + } else { + crate::c_str!(":") + }; + let mut i: size_t = 0; + while (*filters.offset(i as isize)).id != LZMA_VLI_UNKNOWN { + if i == LZMA_FILTERS_MAX as size_t { + str_free(::core::ptr::addr_of_mut!(dest), allocator); + return LZMA_OPTIONS_ERROR; + } + if i > 0 && flags & LZMA_STR_NO_SPACES as u32 == 0 { + str_append_str(::core::ptr::addr_of_mut!(dest), crate::c_str!(" ")); + } + if flags & LZMA_STR_GETOPT_LONG as u32 != 0 + || i > 0 && flags & LZMA_STR_NO_SPACES as u32 != 0 + { + str_append_str(::core::ptr::addr_of_mut!(dest), crate::c_str!("--")); + } + let mut j: size_t = 0; + loop { + if j == (core::mem::size_of::<[filter_codec_def; 11]>()) + .wrapping_div(core::mem::size_of::()) + { + str_free(::core::ptr::addr_of_mut!(dest), allocator); + return LZMA_OPTIONS_ERROR; + } + if filter_name_map[j as usize].id == (*filters.offset(i as isize)).id { + str_append_str( + ::core::ptr::addr_of_mut!(dest), + ::core::ptr::addr_of!( + (*(::core::ptr::addr_of!(filter_name_map) as *const filter_codec_def) + .offset(j as isize)) + .name + ) as *const c_char, + ); + if !show_opts { + break; + } + if (*filters.offset(i as isize)).options.is_null() { + if !filter_name_map[j as usize].allow_null { + str_free(::core::ptr::addr_of_mut!(dest), allocator); + return LZMA_OPTIONS_ERROR; + } + break; + } else { + let optmap_count: size_t = (if flags & LZMA_STR_ENCODER as u32 != 0 { + filter_name_map[j as usize].strfy_encoder + } else { + filter_name_map[j as usize].strfy_decoder + }) as size_t; + strfy_filter( + ::core::ptr::addr_of_mut!(dest), + opt_delim, + filter_name_map[j as usize].optmap, + optmap_count, + (*filters.offset(i as isize)).options, + ); + break; + } + } else { + j += 1; + } + } + i += 1; + } + str_finish(output_str, ::core::ptr::addr_of_mut!(dest), allocator) +} +pub unsafe fn lzma_str_list_filters( + output_str: *mut *mut c_char, + filter_id: lzma_vli, + flags: u32, + allocator: *const lzma_allocator, +) -> lzma_ret { + if output_str.is_null() { + return LZMA_PROG_ERROR; + } + *output_str = core::ptr::null_mut(); + let supported_flags: u32 = LZMA_STR_ALL_FILTERS as u32 + | LZMA_STR_ENCODER as u32 + | LZMA_STR_DECODER as u32 + | LZMA_STR_GETOPT_LONG as u32; + if flags & !supported_flags != 0 { + return LZMA_OPTIONS_ERROR; + } + let mut dest: lzma_str = lzma_str { + buf: core::ptr::null_mut(), + pos: 0, + }; + let ret_: lzma_ret = str_init(::core::ptr::addr_of_mut!(dest), allocator); + if ret_ != LZMA_OK { + return ret_; + } + let show_opts: bool = flags & (LZMA_STR_ENCODER as u32 | LZMA_STR_DECODER as u32) != 0; + let filter_delim: *const c_char = if show_opts { + crate::c_str!("\n") + } else { + crate::c_str!(" ") + }; + let opt_delim: *const c_char = if flags & LZMA_STR_GETOPT_LONG as u32 != 0 { + crate::c_str!("=") + } else { + crate::c_str!(":") + }; + let mut first_filter_printed: bool = false; + let mut i: size_t = 0; + while i + < (core::mem::size_of::<[filter_codec_def; 11]>()) + .wrapping_div(core::mem::size_of::()) + { + if filter_id == LZMA_VLI_UNKNOWN || filter_id == filter_name_map[i as usize].id { + if filter_name_map[i as usize].id < LZMA_FILTER_RESERVED_START + || flags & LZMA_STR_ALL_FILTERS as u32 != 0 + || filter_id != LZMA_VLI_UNKNOWN + { + if first_filter_printed { + str_append_str(::core::ptr::addr_of_mut!(dest), filter_delim); + } + first_filter_printed = true; + if flags & LZMA_STR_GETOPT_LONG as u32 != 0 { + str_append_str(::core::ptr::addr_of_mut!(dest), crate::c_str!("--")); + } + str_append_str( + ::core::ptr::addr_of_mut!(dest), + ::core::ptr::addr_of!( + (*(::core::ptr::addr_of!(filter_name_map) as *const filter_codec_def) + .offset(i as isize)) + .name + ) as *const c_char, + ); + if show_opts { + let optmap: *const option_map = filter_name_map[i as usize].optmap; + let mut d: *const c_char = opt_delim; + let end: size_t = (if flags & LZMA_STR_ENCODER as u32 != 0 { + filter_name_map[i as usize].strfy_encoder + } else { + filter_name_map[i as usize].strfy_decoder + }) as size_t; + let mut j: size_t = 0; + while j < end { + str_append_str(::core::ptr::addr_of_mut!(dest), d); + d = crate::c_str!(","); + str_append_str( + ::core::ptr::addr_of_mut!(dest), + ::core::ptr::addr_of!((*optmap.offset(j as isize)).name) + as *const c_char, + ); + str_append_str(::core::ptr::addr_of_mut!(dest), crate::c_str!("=<")); + if (*optmap.offset(j as isize)).type_0 == OPTMAP_TYPE_LZMA_PRESET { + str_append_str( + ::core::ptr::addr_of_mut!(dest), + LZMA12_PRESET_STR.as_ptr(), + ); + } else if (*optmap.offset(j as isize)).flags & OPTMAP_USE_NAME_VALUE_MAP + != 0 + { + let m: *const name_value_map = (*optmap.offset(j as isize)).u.map; + let mut k: size_t = 0; + while (*m.offset(k as isize)).name[0] != 0 { + if k > 0 { + str_append_str( + ::core::ptr::addr_of_mut!(dest), + crate::c_str!("|"), + ); + } + str_append_str( + ::core::ptr::addr_of_mut!(dest), + ::core::ptr::addr_of!((*m.offset(k as isize)).name) + as *const c_char, + ); + k += 1; + } + } else { + let use_byte_suffix: bool = + (*optmap.offset(j as isize)).flags & OPTMAP_USE_BYTE_SUFFIX != 0; + str_append_u32( + ::core::ptr::addr_of_mut!(dest), + (*optmap.offset(j as isize)).u.range.min, + use_byte_suffix, + ); + str_append_str(::core::ptr::addr_of_mut!(dest), crate::c_str!("-")); + str_append_u32( + ::core::ptr::addr_of_mut!(dest), + (*optmap.offset(j as isize)).u.range.max, + use_byte_suffix, + ); + } + str_append_str(::core::ptr::addr_of_mut!(dest), crate::c_str!(">")); + j += 1; + } + } + } + } + i += 1; + } + if !first_filter_printed { + str_free(::core::ptr::addr_of_mut!(dest), allocator); + return LZMA_OPTIONS_ERROR; + } + str_finish(output_str, ::core::ptr::addr_of_mut!(dest), allocator) +} +unsafe extern "C" fn run_static_initializers() { + lzma12_optmap = [ + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"preset\0\0\0\0\0\0"), + type_0: OPTMAP_TYPE_LZMA_PRESET, + flags: 0, + offset: 0, + u: option_value { + map: core::ptr::null(), + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"dict\0\0\0\0\0\0\0\0"), + type_0: 0, + flags: OPTMAP_USE_BYTE_SUFFIX, + offset: 0, + u: option_value { + range: option_value_range { + min: LZMA_DICT_SIZE_MIN as u32, + max: (1u32 << 30).wrapping_add(1 << 29), + }, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"lc\0\0\0\0\0\0\0\0\0\0"), + type_0: 0, + flags: 0, + offset: 20, + u: option_value { + range: option_value_range { + min: LZMA_LCLP_MIN, + max: LZMA_LCLP_MAX, + }, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"lp\0\0\0\0\0\0\0\0\0\0"), + type_0: 0, + flags: 0, + offset: 24, + u: option_value { + range: option_value_range { + min: LZMA_LCLP_MIN, + max: LZMA_LCLP_MAX, + }, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"pb\0\0\0\0\0\0\0\0\0\0"), + type_0: 0, + flags: 0, + offset: 28, + u: option_value { + range: option_value_range { + min: LZMA_PB_MIN, + max: LZMA_PB_MAX, + }, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"mode\0\0\0\0\0\0\0\0"), + type_0: OPTMAP_TYPE_LZMA_MODE, + flags: OPTMAP_USE_NAME_VALUE_MAP, + offset: 32, + u: option_value { + map: ::core::ptr::addr_of!(lzma12_mode_map) as *const name_value_map, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"nice\0\0\0\0\0\0\0\0"), + type_0: 0, + flags: 0, + offset: 36, + u: option_value { + range: option_value_range { min: 2, max: 273 }, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"mf\0\0\0\0\0\0\0\0\0\0"), + type_0: OPTMAP_TYPE_LZMA_MATCH_FINDER, + flags: OPTMAP_USE_NAME_VALUE_MAP, + offset: 40, + u: option_value { + map: ::core::ptr::addr_of!(lzma12_mf_map) as *const name_value_map, + }, + }, + option_map { + name: core::mem::transmute::<[u8; 12], [c_char; 12]>(*b"depth\0\0\0\0\0\0\0"), + type_0: 0, + flags: 0, + offset: 44, + u: option_value { + range: option_value_range { + min: 0, + max: UINT32_MAX, + }, + }, + }, + ]; +} +#[used] +#[cfg_attr(target_os = "linux", link_section = ".init_array")] +#[cfg_attr(target_os = "windows", link_section = ".CRT$XIB")] +#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")] +static INIT_ARRAY: [unsafe extern "C" fn(); 1] = [run_static_initializers]; diff --git a/liblzma-rs/src/common/vli_decoder.rs b/liblzma-rs/src/common/vli_decoder.rs new file mode 100644 index 00000000..96fa2606 --- /dev/null +++ b/liblzma-rs/src/common/vli_decoder.rs @@ -0,0 +1,54 @@ +use crate::types::*; +pub unsafe fn lzma_vli_decode( + vli: *mut lzma_vli, + mut vli_pos: *mut size_t, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + let mut vli_pos_internal: size_t = 0; + if vli_pos.is_null() { + vli_pos = ::core::ptr::addr_of_mut!(vli_pos_internal); + *vli = 0; + if *in_pos >= in_size { + return LZMA_DATA_ERROR; + } + } else { + if *vli_pos == 0 { + *vli = 0; + } + if *vli_pos >= LZMA_VLI_BYTES_MAX as size_t || *vli >> (*vli_pos * 7) != 0 { + return LZMA_PROG_ERROR; + } + if *in_pos >= in_size { + return LZMA_BUF_ERROR; + } + } + loop { + let byte: u8 = *in_0.offset(*in_pos as isize); + *in_pos += 1; + *vli += ((byte & 0x7f) as lzma_vli) << (*vli_pos * 7); + *vli_pos += 1; + if byte & 0x80 == 0 { + if byte == 0 && *vli_pos > 1 { + return LZMA_DATA_ERROR; + } + return if vli_pos == ::core::ptr::addr_of_mut!(vli_pos_internal) { + LZMA_OK + } else { + LZMA_STREAM_END + }; + } + if *vli_pos == LZMA_VLI_BYTES_MAX as size_t { + return LZMA_DATA_ERROR; + } + if *in_pos >= in_size { + break; + } + } + if vli_pos == ::core::ptr::addr_of_mut!(vli_pos_internal) { + LZMA_DATA_ERROR + } else { + LZMA_OK + } +} diff --git a/liblzma-rs/src/common/vli_encoder.rs b/liblzma-rs/src/common/vli_encoder.rs new file mode 100644 index 00000000..f343feec --- /dev/null +++ b/liblzma-rs/src/common/vli_encoder.rs @@ -0,0 +1,43 @@ +use crate::types::*; +pub unsafe fn lzma_vli_encode( + mut vli: lzma_vli, + mut vli_pos: *mut size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + let mut vli_pos_internal: size_t = 0; + if vli_pos.is_null() { + vli_pos = ::core::ptr::addr_of_mut!(vli_pos_internal); + if *out_pos >= out_size { + return LZMA_PROG_ERROR; + } + } else if *out_pos >= out_size { + return LZMA_BUF_ERROR; + } + if *vli_pos >= LZMA_VLI_BYTES_MAX as size_t || vli > LZMA_VLI_MAX { + return LZMA_PROG_ERROR; + } + vli >>= *vli_pos * 7; + while vli >= 0x80 { + *vli_pos += 1; + *out.offset(*out_pos as isize) = vli as u8 | 0x80; + vli >>= 7; + *out_pos += 1; + if *out_pos == out_size { + return if vli_pos == ::core::ptr::addr_of_mut!(vli_pos_internal) { + LZMA_PROG_ERROR + } else { + LZMA_OK + }; + } + } + *out.offset(*out_pos as isize) = vli as u8; + *out_pos += 1; + *vli_pos += 1; + if vli_pos == ::core::ptr::addr_of_mut!(vli_pos_internal) { + LZMA_OK + } else { + LZMA_STREAM_END + } +} diff --git a/liblzma-rs/src/common/vli_size.rs b/liblzma-rs/src/common/vli_size.rs new file mode 100644 index 00000000..1106fe77 --- /dev/null +++ b/liblzma-rs/src/common/vli_size.rs @@ -0,0 +1,15 @@ +use crate::types::*; +pub fn lzma_vli_size(mut vli: lzma_vli) -> u32 { + if vli > LZMA_VLI_MAX { + return 0; + } + let mut i: u32 = 0; + loop { + vli >>= 7; + i += 1; + if vli == 0 { + break; + } + } + i +} diff --git a/liblzma-rs/src/delta/delta_common.rs b/liblzma-rs/src/delta/delta_common.rs new file mode 100644 index 00000000..50321d75 --- /dev/null +++ b/liblzma-rs/src/delta/delta_common.rs @@ -0,0 +1,61 @@ +use crate::types::*; +unsafe extern "C" fn delta_coder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_delta_coder = coder_ptr as *mut lzma_delta_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +pub unsafe fn lzma_delta_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + let mut coder: *mut lzma_delta_coder = (*next).coder as *mut lzma_delta_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).end = + Some(delta_coder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> ()); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + if lzma_delta_coder_memusage((*filters).options) == UINT64_MAX { + return LZMA_OPTIONS_ERROR; + } + let opt: *const lzma_options_delta = (*filters).options as *const lzma_options_delta; + (*coder).distance = (*opt).dist as size_t; + (*coder).pos = 0; + core::ptr::write_bytes( + ::core::ptr::addr_of_mut!((*coder).history) as *mut u8, + 0 as u8, + 256, + ); + lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + filters.offset(1), + ) +} +pub unsafe extern "C" fn lzma_delta_coder_memusage(options: *const c_void) -> u64 { + let opt: *const lzma_options_delta = options as *const lzma_options_delta; + if opt.is_null() + || (*opt).type_0 != LZMA_DELTA_TYPE_BYTE + || (*opt).dist < LZMA_DELTA_DIST_MIN + || (*opt).dist > LZMA_DELTA_DIST_MAX + { + return UINT64_MAX; + } + core::mem::size_of::() as u64 +} diff --git a/liblzma-rs/src/delta/delta_decoder.rs b/liblzma-rs/src/delta/delta_decoder.rs new file mode 100644 index 00000000..eb6f25bf --- /dev/null +++ b/liblzma-rs/src/delta/delta_decoder.rs @@ -0,0 +1,85 @@ +use crate::types::*; +unsafe fn decode_buffer(coder: *mut lzma_delta_coder, buffer: *mut u8, size: size_t) { + let distance: size_t = (*coder).distance; + let mut i: size_t = 0; + while i < size { + *buffer.offset(i as isize) = (*buffer.offset(i as isize)).wrapping_add( + (*coder).history[(distance.wrapping_add((*coder).pos as size_t) & 0xff) as usize], + ); + (*coder).history[((*coder).pos & 0xff) as usize] = *buffer.offset(i as isize); + (*coder).pos = (*coder).pos.wrapping_sub(1); + i += 1; + } +} +unsafe extern "C" fn delta_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_delta_coder = coder_ptr as *mut lzma_delta_coder; + let out_start: size_t = *out_pos; + let ret: lzma_ret = (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + debug_assert!(*out_pos >= out_start); + let size: size_t = *out_pos - out_start; + if size > 0 { + decode_buffer(coder, out.offset(out_start as isize), size); + } + ret +} +pub unsafe extern "C" fn lzma_delta_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + (*next).code = Some( + delta_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + lzma_delta_coder_init(next, allocator, filters) +} +pub unsafe extern "C" fn lzma_delta_props_decode( + options: *mut *mut c_void, + allocator: *const lzma_allocator, + props: *const u8, + props_size: size_t, +) -> lzma_ret { + if props_size != 1 { + return LZMA_OPTIONS_ERROR; + } + let opt: *mut lzma_options_delta = + lzma_alloc(core::mem::size_of::(), allocator) + as *mut lzma_options_delta; + if opt.is_null() { + return LZMA_MEM_ERROR; + } + (*opt).type_0 = LZMA_DELTA_TYPE_BYTE; + (*opt).dist = u32::from(*props) + 1; + *options = opt as *mut c_void; + LZMA_OK +} diff --git a/liblzma-rs/src/delta/delta_encoder.rs b/liblzma-rs/src/delta/delta_encoder.rs new file mode 100644 index 00000000..a50640d1 --- /dev/null +++ b/liblzma-rs/src/delta/delta_encoder.rs @@ -0,0 +1,141 @@ +use crate::types::*; +unsafe fn copy_and_encode( + coder: *mut lzma_delta_coder, + in_0: *const u8, + out: *mut u8, + size: size_t, +) { + let distance: size_t = (*coder).distance; + let mut i: size_t = 0; + while i < size { + let tmp: u8 = + (*coder).history[(distance.wrapping_add((*coder).pos as size_t) & 0xff) as usize]; + (*coder).history[((*coder).pos & 0xff) as usize] = *in_0.offset(i as isize); + (*coder).pos = (*coder).pos.wrapping_sub(1); + *out.offset(i as isize) = (*in_0.offset(i as isize)).wrapping_sub(tmp); + i += 1; + } +} +unsafe fn encode_in_place(coder: *mut lzma_delta_coder, buffer: *mut u8, size: size_t) { + let distance: size_t = (*coder).distance; + let mut i: size_t = 0; + while i < size { + let tmp: u8 = + (*coder).history[(distance.wrapping_add((*coder).pos as size_t) & 0xff) as usize]; + (*coder).history[((*coder).pos & 0xff) as usize] = *buffer.offset(i as isize); + (*coder).pos = (*coder).pos.wrapping_sub(1); + *buffer.offset(i as isize) = (*buffer.offset(i as isize)).wrapping_sub(tmp); + i += 1; + } +} +unsafe extern "C" fn delta_encode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_delta_coder = coder_ptr as *mut lzma_delta_coder; + let mut ret: lzma_ret = LZMA_OK; + if (*coder).next.code.is_none() { + debug_assert!(in_size >= *in_pos); + debug_assert!(out_size >= *out_pos); + let in_avail: size_t = in_size - *in_pos; + let out_avail: size_t = out_size - *out_pos; + let size: size_t = if in_avail < out_avail { + in_avail + } else { + out_avail + }; + if size > 0 { + copy_and_encode( + coder, + in_0.offset(*in_pos as isize), + out.offset(*out_pos as isize), + size, + ); + } + *in_pos += size; + *out_pos += size; + ret = if action != LZMA_RUN && *in_pos == in_size { + LZMA_STREAM_END + } else { + LZMA_OK + }; + } else { + let out_start: size_t = *out_pos; + ret = (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + debug_assert!(*out_pos >= out_start); + let size_0: size_t = *out_pos - out_start; + if size_0 > 0 { + encode_in_place(coder, out.offset(out_start as isize), size_0); + } + } + ret +} +unsafe extern "C" fn delta_encoder_update( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + _filters_null: *const lzma_filter, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_delta_coder = coder_ptr as *mut lzma_delta_coder; + lzma_next_filter_update( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + reversed_filters.offset(1), + ) +} +pub unsafe extern "C" fn lzma_delta_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + (*next).code = Some( + delta_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).update = Some( + delta_encoder_update + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + ); + lzma_delta_coder_init(next, allocator, filters) +} +pub unsafe extern "C" fn lzma_delta_props_encode(options: *const c_void, out: *mut u8) -> lzma_ret { + if lzma_delta_coder_memusage(options) == UINT64_MAX { + return LZMA_PROG_ERROR; + } + let opt: *const lzma_options_delta = options as *const lzma_options_delta; + debug_assert!((*opt).dist >= LZMA_DELTA_DIST_MIN); + *out = ((*opt).dist - LZMA_DELTA_DIST_MIN) as u8; + LZMA_OK +} diff --git a/liblzma-rs/src/delta/mod.rs b/liblzma-rs/src/delta/mod.rs new file mode 100644 index 00000000..a584bd21 --- /dev/null +++ b/liblzma-rs/src/delta/mod.rs @@ -0,0 +1,3 @@ +pub mod delta_common; +pub mod delta_decoder; +pub mod delta_encoder; diff --git a/liblzma-rs/src/lib.rs b/liblzma-rs/src/lib.rs new file mode 100644 index 00000000..5f304142 --- /dev/null +++ b/liblzma-rs/src/lib.rs @@ -0,0 +1,25 @@ +#![allow( + clashing_extern_declarations, + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + clippy::all +)] +#[macro_export] +macro_rules! c_str { + ($s:literal) => { + concat!($s, "\0").as_ptr() as *const ::std::os::raw::c_char + }; +} +pub mod alloc; +pub mod check; +pub mod common; +pub mod delta; +pub mod lz; +pub mod lzma; +pub mod rangecoder; +pub mod simple; +pub mod tuklib; +pub mod types; diff --git a/liblzma-rs/src/lz/lz_decoder.rs b/liblzma-rs/src/lz/lz_decoder.rs new file mode 100644 index 00000000..1a4ede50 --- /dev/null +++ b/liblzma-rs/src/lz/lz_decoder.rs @@ -0,0 +1,308 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lz_options { + pub dict_size: size_t, + pub preset_dict: *const u8, + pub preset_dict_size: size_t, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_coder { + pub dict: lzma_dict, + pub lz: lzma_lz_decoder, + pub next: lzma_next_coder, + pub next_finished: bool, + pub this_finished: bool, + pub temp: lz_decoder_temp_buf, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lz_decoder_temp_buf { + pub pos: size_t, + pub size: size_t, + pub buffer: [u8; LZMA_BUFFER_SIZE as usize], +} +pub const LZMA_BUFFER_SIZE: u32 = 4096; +pub const LZ_DICT_EXTRA: u32 = 0; +pub const LZMA_LZ_DECODER_INIT: lzma_lz_decoder = lzma_lz_decoder { + coder: core::ptr::null_mut(), + code: None, + reset: None, + set_uncompressed: None, + end: None, +}; +unsafe fn lz_decoder_reset(coder: *mut lzma_coder) { + (*coder).dict.pos = LZ_DICT_INIT_POS as size_t; + (*coder).dict.full = 0; + *(*coder).dict.buf.offset((LZ_DICT_INIT_POS - 1) as isize) = '\0' as i32 as u8; + (*coder).dict.has_wrapped = false; + (*coder).dict.need_reset = false; +} +unsafe fn decode_buffer( + coder: *mut lzma_coder, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + loop { + if (*coder).dict.pos == (*coder).dict.size { + (*coder).dict.pos = LZ_DICT_REPEAT_MAX as size_t; + (*coder).dict.has_wrapped = true; + core::ptr::copy_nonoverlapping( + (*coder) + .dict + .buf + .offset((*coder).dict.size as isize) + .offset(-(LZ_DICT_REPEAT_MAX as isize)) as *const u8, + (*coder).dict.buf as *mut u8, + LZ_DICT_REPEAT_MAX as size_t, + ); + } + let dict_start: size_t = (*coder).dict.pos; + (*coder).dict.limit = (*coder).dict.pos.wrapping_add( + if out_size.wrapping_sub(*out_pos) < (*coder).dict.size.wrapping_sub((*coder).dict.pos) + { + out_size.wrapping_sub(*out_pos) + } else { + (*coder).dict.size.wrapping_sub((*coder).dict.pos) + }, + ); + let ret: lzma_ret = (*coder).lz.code.unwrap()( + (*coder).lz.coder, + ::core::ptr::addr_of_mut!((*coder).dict), + in_0, + in_pos, + in_size, + ); + let copy_size: size_t = (*coder).dict.pos.wrapping_sub(dict_start); + if copy_size > 0 { + core::ptr::copy_nonoverlapping( + (*coder).dict.buf.offset(dict_start as isize) as *const u8, + out.offset(*out_pos as isize) as *mut u8, + copy_size, + ); + } + *out_pos = (*out_pos).wrapping_add(copy_size); + if (*coder).dict.need_reset { + lz_decoder_reset(coder); + if ret != LZMA_OK || *out_pos == out_size { + return ret; + } + } else if ret != LZMA_OK || *out_pos == out_size || (*coder).dict.pos < (*coder).dict.size { + return ret; + } + } +} +unsafe extern "C" fn lz_decode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; + if (*coder).next.code.is_none() { + return decode_buffer(coder, in_0, in_pos, in_size, out, out_pos, out_size); + } + while *out_pos < out_size { + if !(*coder).next_finished && (*coder).temp.pos == (*coder).temp.size { + (*coder).temp.pos = 0; + (*coder).temp.size = 0; + let ret: lzma_ret = (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).temp.buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).temp.size), + LZMA_BUFFER_SIZE as size_t, + action, + ); + if ret == LZMA_STREAM_END { + (*coder).next_finished = true; + } else if ret != LZMA_OK || (*coder).temp.size == 0 { + return ret; + } + } + if (*coder).this_finished { + if (*coder).temp.size != 0 { + return LZMA_DATA_ERROR; + } + if (*coder).next_finished { + return LZMA_STREAM_END; + } + return LZMA_OK; + } + let ret_0: lzma_ret = decode_buffer( + coder, + ::core::ptr::addr_of_mut!((*coder).temp.buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).temp.pos), + (*coder).temp.size, + out, + out_pos, + out_size, + ); + if ret_0 == LZMA_STREAM_END { + (*coder).this_finished = true; + } else if ret_0 != LZMA_OK { + return ret_0; + } else if (*coder).next_finished && *out_pos < out_size { + return LZMA_DATA_ERROR; + } + } + LZMA_OK +} +unsafe extern "C" fn lz_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free((*coder).dict.buf as *mut c_void, allocator); + if (*coder).lz.end.is_some() { + (*coder).lz.end.unwrap()((*coder).lz.coder, allocator); + } else { + crate::alloc::internal_free((*coder).lz.coder, allocator); + } + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +pub unsafe fn lzma_lz_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + lz_init: Option< + unsafe extern "C" fn( + *mut lzma_lz_decoder, + *const lzma_allocator, + lzma_vli, + *const c_void, + *mut lzma_lz_options, + ) -> lzma_ret, + >, +) -> lzma_ret { + let mut coder: *mut lzma_coder = (*next).coder as *mut lzma_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + lz_decode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = + Some(lz_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> ()); + (*coder).dict.buf = core::ptr::null_mut(); + (*coder).dict.size = 0; + (*coder).lz = LZMA_LZ_DECODER_INIT; + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + let mut lz_options: lzma_lz_options = lzma_lz_options { + dict_size: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + }; + let lz_init = if let Some(lz_init) = lz_init { + lz_init + } else { + return LZMA_PROG_ERROR; + }; + let ret_: lzma_ret = lz_init( + ::core::ptr::addr_of_mut!((*coder).lz), + allocator, + (*filters).id, + (*filters).options, + ::core::ptr::addr_of_mut!(lz_options), + ); + if ret_ != LZMA_OK { + return ret_; + } + if (*coder).lz.code.is_none() { + return LZMA_PROG_ERROR; + } + if lz_options.dict_size < 4096 { + lz_options.dict_size = 4096; + } + if lz_options.dict_size + > (SIZE_MAX as size_t) + .wrapping_sub(15) + .wrapping_sub((2 * LZ_DICT_REPEAT_MAX) as size_t) + .wrapping_sub(LZ_DICT_EXTRA as size_t) + { + return LZMA_MEM_ERROR; + } + lz_options.dict_size = lz_options.dict_size.wrapping_add(15) & !(15); + let alloc_size: size_t = lz_options + .dict_size + .wrapping_add((2 * LZ_DICT_REPEAT_MAX) as size_t); + if (*coder).dict.size != alloc_size { + crate::alloc::internal_free((*coder).dict.buf as *mut c_void, allocator); + (*coder).dict.buf = crate::alloc::internal_alloc_bytes( + alloc_size.wrapping_add(LZ_DICT_EXTRA as size_t), + allocator, + ) as *mut u8; + if (*coder).dict.buf.is_null() { + return LZMA_MEM_ERROR; + } + (*coder).dict.size = alloc_size; + } + lz_decoder_reset((*next).coder as *mut lzma_coder); + if !lz_options.preset_dict.is_null() && lz_options.preset_dict_size > 0 { + let copy_size: size_t = if lz_options.preset_dict_size < lz_options.dict_size { + lz_options.preset_dict_size + } else { + lz_options.dict_size + }; + let offset: size_t = lz_options.preset_dict_size.wrapping_sub(copy_size); + core::ptr::copy_nonoverlapping( + lz_options.preset_dict.offset(offset as isize) as *const u8, + (*coder).dict.buf.offset((*coder).dict.pos as isize) as *mut u8, + copy_size, + ); + (*coder).dict.pos = (*coder).dict.pos.wrapping_add(copy_size); + (*coder).dict.full = copy_size; + } + (*coder).next_finished = false; + (*coder).this_finished = false; + (*coder).temp.pos = 0; + (*coder).temp.size = 0; + lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + filters.offset(1), + ) +} +pub fn lzma_lz_decoder_memusage(dictionary_size: size_t) -> u64 { + (core::mem::size_of::() as u64) + .wrapping_add(dictionary_size as u64) + .wrapping_add((2 * LZ_DICT_REPEAT_MAX) as u64) + .wrapping_add(LZ_DICT_EXTRA as u64) +} diff --git a/liblzma-rs/src/lz/lz_encoder.rs b/liblzma-rs/src/lz/lz_encoder.rs new file mode 100644 index 00000000..7148d3ef --- /dev/null +++ b/liblzma-rs/src/lz/lz_encoder.rs @@ -0,0 +1,526 @@ +use crate::lz::lz_encoder_mf::{ + lzma_mf_bt2_find, lzma_mf_bt2_skip, lzma_mf_bt3_find, lzma_mf_bt3_skip, lzma_mf_bt4_find, + lzma_mf_bt4_skip, lzma_mf_hc3_find, lzma_mf_hc3_skip, lzma_mf_hc4_find, lzma_mf_hc4_skip, +}; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lz_options { + pub before_size: size_t, + pub dict_size: size_t, + pub after_size: size_t, + pub match_len_max: size_t, + pub nice_len: size_t, + pub match_finder: lzma_match_finder, + pub depth: u32, + pub preset_dict: *const u8, + pub preset_dict_size: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_coder { + pub lz: lzma_lz_encoder, + pub mf: lzma_mf, + pub next: lzma_next_coder, +} +pub const LZMA_MEMCMPLEN_EXTRA: u32 = 0; +#[inline] +unsafe fn move_window(mf: *mut lzma_mf) { + debug_assert!((*mf).read_pos > (*mf).keep_size_before); + let move_offset: u32 = ((*mf).read_pos - (*mf).keep_size_before) & !15; + debug_assert!((*mf).write_pos > move_offset); + let move_size: size_t = ((*mf).write_pos - move_offset) as size_t; + core::ptr::copy( + (*mf).buffer.offset(move_offset as isize) as *const u8, + (*mf).buffer as *mut u8, + move_size, + ); + (*mf).offset += move_offset; + (*mf).read_pos -= move_offset; + (*mf).read_limit -= move_offset; + (*mf).write_pos -= move_offset; +} +unsafe fn fill_window( + coder: *mut lzma_coder, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + action: lzma_action, +) -> lzma_ret { + debug_assert!((*coder).mf.read_pos <= (*coder).mf.write_pos); + if (*coder).mf.read_pos >= (*coder).mf.size - (*coder).mf.keep_size_after { + move_window(::core::ptr::addr_of_mut!((*coder).mf)); + } + let mut write_pos: size_t = (*coder).mf.write_pos as size_t; + let mut ret = if (*coder).next.code.is_none() { + lzma_bufcpy( + in_0, + in_pos, + in_size, + (*coder).mf.buffer, + ::core::ptr::addr_of_mut!(write_pos), + (*coder).mf.size as size_t, + ); + if action != LZMA_RUN && *in_pos == in_size { + LZMA_STREAM_END + } else { + LZMA_OK + } + } else { + (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + (*coder).mf.buffer, + ::core::ptr::addr_of_mut!(write_pos), + (*coder).mf.size as size_t, + action, + ) + }; + (*coder).mf.write_pos = write_pos as u32; + core::ptr::write_bytes( + (*coder).mf.buffer.offset(write_pos as isize) as *mut u8, + 0 as u8, + 0, + ); + if ret == LZMA_STREAM_END { + ret = LZMA_OK; + (*coder).mf.action = action; + (*coder).mf.read_limit = (*coder).mf.write_pos; + } else if (*coder).mf.write_pos > (*coder).mf.keep_size_after { + (*coder).mf.read_limit = (*coder).mf.write_pos - (*coder).mf.keep_size_after; + } + if (*coder).mf.pending > 0 && (*coder).mf.read_pos < (*coder).mf.read_limit { + let pending: u32 = (*coder).mf.pending; + (*coder).mf.pending = 0; + debug_assert!((*coder).mf.read_pos >= pending); + (*coder).mf.read_pos -= pending; + (*coder).mf.skip.unwrap()(::core::ptr::addr_of_mut!((*coder).mf), pending); + } + ret +} +unsafe extern "C" fn lz_encode( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; + while *out_pos < out_size && (*in_pos < in_size || action != LZMA_RUN) { + if (*coder).mf.action == LZMA_RUN && (*coder).mf.read_pos >= (*coder).mf.read_limit { + let ret_: lzma_ret = fill_window(coder, allocator, in_0, in_pos, in_size, action); + if ret_ != LZMA_OK { + return ret_; + } + } + let ret: lzma_ret = (*coder).lz.code.unwrap()( + (*coder).lz.coder, + ::core::ptr::addr_of_mut!((*coder).mf), + out, + out_pos, + out_size, + ); + if ret != LZMA_OK { + (*coder).mf.action = LZMA_RUN; + return ret; + } + } + LZMA_OK +} +unsafe fn lz_encoder_prepare( + mf: *mut lzma_mf, + allocator: *const lzma_allocator, + lz_options: *const lzma_lz_options, +) -> bool { + if (*lz_options).dict_size < LZMA_DICT_SIZE_MIN as size_t + || (*lz_options).dict_size > ((1u32 << 30) + (1u32 << 29)) as size_t + || (*lz_options).nice_len > (*lz_options).match_len_max + { + return true; + } + (*mf).keep_size_before = ((*lz_options).before_size + (*lz_options).dict_size) as u32; + (*mf).keep_size_after = ((*lz_options).after_size + (*lz_options).match_len_max) as u32; + let mut reserve: u32 = ((*lz_options).dict_size / 2) as u32; + if reserve > 1 << 30 { + reserve /= 2; + } + reserve += + (((*lz_options).before_size + (*lz_options).match_len_max + (*lz_options).after_size) / 2 + + (1u32 << 19) as size_t) as u32; + let old_size: u32 = (*mf).size; + (*mf).size = (*mf).keep_size_before + reserve + (*mf).keep_size_after; + if !(*mf).buffer.is_null() && old_size != (*mf).size { + crate::alloc::internal_free((*mf).buffer as *mut c_void, allocator); + (*mf).buffer = core::ptr::null_mut(); + } + (*mf).match_len_max = (*lz_options).match_len_max as u32; + (*mf).nice_len = (*lz_options).nice_len as u32; + (*mf).cyclic_size = (*lz_options).dict_size as u32 + 1; + match (*lz_options).match_finder { + 3 => { + (*mf).find = Some( + lzma_mf_hc3_find as unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32, + ); + (*mf).skip = Some(lzma_mf_hc3_skip as unsafe extern "C" fn(*mut lzma_mf, u32) -> ()); + } + 4 => { + (*mf).find = Some( + lzma_mf_hc4_find as unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32, + ); + (*mf).skip = Some(lzma_mf_hc4_skip as unsafe extern "C" fn(*mut lzma_mf, u32) -> ()); + } + 18 => { + (*mf).find = Some( + lzma_mf_bt2_find as unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32, + ); + (*mf).skip = Some(lzma_mf_bt2_skip as unsafe extern "C" fn(*mut lzma_mf, u32) -> ()); + } + 19 => { + (*mf).find = Some( + lzma_mf_bt3_find as unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32, + ); + (*mf).skip = Some(lzma_mf_bt3_skip as unsafe extern "C" fn(*mut lzma_mf, u32) -> ()); + } + 20 => { + (*mf).find = Some( + lzma_mf_bt4_find as unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32, + ); + (*mf).skip = Some(lzma_mf_bt4_skip as unsafe extern "C" fn(*mut lzma_mf, u32) -> ()); + } + _ => return true, + } + let hash_bytes: u32 = mf_get_hash_bytes((*lz_options).match_finder) as u32; + let is_bt: bool = (*lz_options).match_finder & 0x10 != 0; + let mut hs: u32 = 0; + if hash_bytes == 2 { + hs = 0xffff; + } else { + hs = (*lz_options).dict_size as u32 - 1; + hs |= hs >> 1; + hs |= hs >> 2; + hs |= hs >> 4; + hs |= hs >> 8; + hs >>= 1; + hs |= 0xffff; + if hs > 1 << 24 { + if hash_bytes == 3 { + hs = (1u32 << 24) - 1; + } else { + hs >>= 1; + } + } + } + (*mf).hash_mask = hs; + hs += 1; + if hash_bytes > 2 { + hs += HASH_2_SIZE; + } + if hash_bytes > 3 { + hs += HASH_3_SIZE; + } + let old_hash_count: u32 = (*mf).hash_count; + let old_sons_count: u32 = (*mf).sons_count; + (*mf).hash_count = hs; + (*mf).sons_count = (*mf).cyclic_size; + if is_bt { + (*mf).sons_count *= 2; + } + if old_hash_count != (*mf).hash_count || old_sons_count != (*mf).sons_count { + crate::alloc::internal_free((*mf).hash as *mut c_void, allocator); + (*mf).hash = core::ptr::null_mut(); + crate::alloc::internal_free((*mf).son as *mut c_void, allocator); + (*mf).son = core::ptr::null_mut(); + } + (*mf).depth = (*lz_options).depth; + if (*mf).depth == 0 { + if is_bt { + (*mf).depth = 16u32 + (*mf).nice_len / 2; + } else { + (*mf).depth = 4u32 + (*mf).nice_len / 4; + } + } + false +} +unsafe fn lz_encoder_init( + mf: *mut lzma_mf, + allocator: *const lzma_allocator, + lz_options: *const lzma_lz_options, +) -> bool { + if (*mf).buffer.is_null() { + (*mf).buffer = crate::alloc::internal_alloc_bytes( + ((*mf).size + LZMA_MEMCMPLEN_EXTRA) as size_t, + allocator, + ) as *mut u8; + if (*mf).buffer.is_null() { + return true; + } + core::ptr::write_bytes( + (*mf).buffer.offset((*mf).size as isize) as *mut u8, + 0 as u8, + 0, + ); + } + (*mf).offset = (*mf).cyclic_size; + (*mf).read_pos = 0; + (*mf).read_ahead = 0; + (*mf).read_limit = 0; + (*mf).write_pos = 0; + (*mf).pending = 0; + if (*mf).hash.is_null() { + (*mf).hash = + crate::alloc::internal_alloc_zeroed_array::((*mf).hash_count as size_t, allocator); + (*mf).son = + crate::alloc::internal_alloc_array::((*mf).sons_count as size_t, allocator); + if (*mf).hash.is_null() || (*mf).son.is_null() { + crate::alloc::internal_free((*mf).hash as *mut c_void, allocator); + (*mf).hash = core::ptr::null_mut(); + crate::alloc::internal_free((*mf).son as *mut c_void, allocator); + (*mf).son = core::ptr::null_mut(); + return true; + } + } else { + core::ptr::write_bytes( + (*mf).hash as *mut u8, + 0 as u8, + ((*mf).hash_count as size_t) * core::mem::size_of::(), + ); + } + (*mf).cyclic_pos = 0; + if !(*lz_options).preset_dict.is_null() && (*lz_options).preset_dict_size > 0 { + (*mf).write_pos = if (*lz_options).preset_dict_size < (*mf).size { + (*lz_options).preset_dict_size + } else { + (*mf).size + }; + core::ptr::copy_nonoverlapping( + (*lz_options) + .preset_dict + .offset((*lz_options).preset_dict_size as isize) + .offset(-((*mf).write_pos as isize)) as *const u8, + (*mf).buffer as *mut u8, + (*mf).write_pos as size_t, + ); + (*mf).action = LZMA_SYNC_FLUSH; + (*mf).skip.unwrap()(mf, (*mf).write_pos); + } + (*mf).action = LZMA_RUN; + false +} +pub fn lzma_lz_encoder_memusage(lz_options: *const lzma_lz_options) -> u64 { + let mut mf: lzma_mf = lzma_mf_s { + buffer: core::ptr::null_mut(), + size: 0, + keep_size_before: 0, + keep_size_after: 0, + offset: 0, + read_pos: 0, + read_ahead: 0, + read_limit: 0, + write_pos: 0, + pending: 0, + find: None, + skip: None, + hash: core::ptr::null_mut(), + son: core::ptr::null_mut(), + cyclic_pos: 0, + cyclic_size: 0, + hash_mask: 0, + depth: 0, + nice_len: 0, + match_len_max: 0, + action: LZMA_RUN, + hash_count: 0, + sons_count: 0, + }; + if unsafe { lz_encoder_prepare(::core::ptr::addr_of_mut!(mf), core::ptr::null(), lz_options) } { + return UINT64_MAX; + } + ((mf.hash_count as u64) + (mf.sons_count as u64)) * core::mem::size_of::() as u64 + + mf.size as u64 + + core::mem::size_of::() as u64 +} +unsafe extern "C" fn lz_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free((*coder).mf.son as *mut c_void, allocator); + crate::alloc::internal_free((*coder).mf.hash as *mut c_void, allocator); + crate::alloc::internal_free((*coder).mf.buffer as *mut c_void, allocator); + if (*coder).lz.end.is_some() { + (*coder).lz.end.unwrap()((*coder).lz.coder, allocator); + } else { + crate::alloc::internal_free((*coder).lz.coder, allocator); + } + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn lz_encoder_update( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + _filters_null: *const lzma_filter, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; + if (*coder).lz.options_update.is_none() { + return LZMA_PROG_ERROR; + } + let ret_: lzma_ret = (*coder).lz.options_update.unwrap()((*coder).lz.coder, reversed_filters); + if ret_ != LZMA_OK { + return ret_; + } + lzma_next_filter_update( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + reversed_filters.offset(1), + ) +} +unsafe extern "C" fn lz_encoder_set_out_limit( + coder_ptr: *mut c_void, + uncomp_size: *mut u64, + out_limit: u64, +) -> lzma_ret { + let coder: *mut lzma_coder = coder_ptr as *mut lzma_coder; + if (*coder).next.code.is_none() && (*coder).lz.set_out_limit.is_some() { + return (*coder).lz.set_out_limit.unwrap()((*coder).lz.coder, uncomp_size, out_limit); + } + LZMA_OPTIONS_ERROR +} +pub unsafe fn lzma_lz_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + lz_init: Option< + unsafe extern "C" fn( + *mut lzma_lz_encoder, + *const lzma_allocator, + lzma_vli, + *const c_void, + *mut lzma_lz_options, + ) -> lzma_ret, + >, +) -> lzma_ret { + let mut coder: *mut lzma_coder = (*next).coder as *mut lzma_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + lz_encode + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = + Some(lz_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> ()); + (*next).update = Some( + lz_encoder_update + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + ); + (*next).set_out_limit = Some( + lz_encoder_set_out_limit + as unsafe extern "C" fn(*mut c_void, *mut u64, u64) -> lzma_ret, + ); + (*coder).lz.coder = core::ptr::null_mut(); + (*coder).lz.code = None; + (*coder).lz.end = None; + (*coder).lz.options_update = None; + (*coder).lz.set_out_limit = None; + (*coder).mf.buffer = core::ptr::null_mut(); + (*coder).mf.size = 0; + (*coder).mf.hash = core::ptr::null_mut(); + (*coder).mf.son = core::ptr::null_mut(); + (*coder).mf.hash_count = 0; + (*coder).mf.sons_count = 0; + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + } + let mut lz_options: lzma_lz_options = lzma_lz_options { + before_size: 0, + dict_size: 0, + after_size: 0, + match_len_max: 0, + nice_len: 0, + match_finder: 0, + depth: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + }; + let lz_init = if let Some(lz_init) = lz_init { + lz_init + } else { + return LZMA_PROG_ERROR; + }; + let ret_: lzma_ret = lz_init( + ::core::ptr::addr_of_mut!((*coder).lz), + allocator, + (*filters).id, + (*filters).options, + ::core::ptr::addr_of_mut!(lz_options), + ); + if ret_ != LZMA_OK { + return ret_; + } + if (*coder).lz.code.is_none() { + return LZMA_PROG_ERROR; + } + if lz_encoder_prepare( + ::core::ptr::addr_of_mut!((*coder).mf), + allocator, + ::core::ptr::addr_of_mut!(lz_options), + ) { + return LZMA_OPTIONS_ERROR; + } + if lz_encoder_init( + ::core::ptr::addr_of_mut!((*coder).mf), + allocator, + ::core::ptr::addr_of_mut!(lz_options), + ) { + return LZMA_MEM_ERROR; + } + lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + filters.offset(1), + ) +} +pub fn lzma_mf_is_supported(mf: lzma_match_finder) -> lzma_bool { + match mf { + 3 => return true as lzma_bool, + 4 => return true as lzma_bool, + 18 => return true as lzma_bool, + 19 => return true as lzma_bool, + 20 => return true as lzma_bool, + _ => return false as lzma_bool, + }; +} diff --git a/liblzma-rs/src/lz/lz_encoder_mf.rs b/liblzma-rs/src/lz/lz_encoder_mf.rs new file mode 100644 index 00000000..66c89056 --- /dev/null +++ b/liblzma-rs/src/lz/lz_encoder_mf.rs @@ -0,0 +1,724 @@ +use crate::check::crc32_fast::lzma_crc32_table; +use crate::types::*; +pub const HASH_2_MASK: c_uint = HASH_2_SIZE.wrapping_sub(1); +pub const HASH_3_MASK: c_uint = HASH_3_SIZE.wrapping_sub(1); +pub const FIX_3_HASH_SIZE: c_uint = 1u32 << 10; +pub const FIX_4_HASH_SIZE: c_uint = HASH_2_SIZE.wrapping_add(HASH_3_SIZE); +#[inline] +pub unsafe fn lzma_mf_find(mf: *mut lzma_mf, count_ptr: *mut u32, matches: *mut lzma_match) -> u32 { + lzma_mf_find_raw(mf, count_ptr, matches, (*mf).find.unwrap()) +} + +#[inline(always)] +pub unsafe fn lzma_mf_find_raw( + mf: *mut lzma_mf, + count_ptr: *mut u32, + matches: *mut lzma_match, + find: unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32, +) -> u32 { + let count: u32 = find(mf, matches) as u32; + let mut len_best: u32 = 0; + if count > 0 { + len_best = (*matches.offset((count - 1) as isize)).len; + if len_best == (*mf).nice_len { + let mut limit: u32 = mf_avail(mf) + 1; + if limit > (*mf).match_len_max { + limit = (*mf).match_len_max; + } + let p1: *const u8 = mf_ptr(mf).offset(-1); + let p2: *const u8 = p1 + .offset(-((*matches.offset((count - 1) as isize)).dist as isize)) + .offset(-1); + len_best = lzma_memcmplen(p1, p2, len_best, limit); + } + } + *count_ptr = count; + (*mf).read_ahead += 1; + len_best +} +pub const EMPTY_HASH_VALUE: u32 = 0; +pub const MUST_NORMALIZE_POS: c_uint = UINT32_MAX; +#[cold] +#[inline(never)] +unsafe fn normalize(mf: *mut lzma_mf) { + let subvalue: u32 = MUST_NORMALIZE_POS.wrapping_sub((*mf).cyclic_size); + let mut i: u32 = 0; + while i < (*mf).hash_count { + if *(*mf).hash.offset(i as isize) <= subvalue { + *(*mf).hash.offset(i as isize) = EMPTY_HASH_VALUE; + } else { + *(*mf).hash.offset(i as isize) = + (*(*mf).hash.offset(i as isize)).wrapping_sub(subvalue); + } + i += 1; + } + let mut i_0: u32 = 0; + while i_0 < (*mf).sons_count { + if *(*mf).son.offset(i_0 as isize) <= subvalue { + *(*mf).son.offset(i_0 as isize) = EMPTY_HASH_VALUE; + } else { + *(*mf).son.offset(i_0 as isize) = + (*(*mf).son.offset(i_0 as isize)).wrapping_sub(subvalue); + } + i_0 += 1; + } + (*mf).offset = (*mf).offset.wrapping_sub(subvalue); +} +#[inline(always)] +unsafe fn move_pos(mf: *mut lzma_mf) { + (*mf).cyclic_pos = (*mf).cyclic_pos.wrapping_add(1); + if (*mf).cyclic_pos == (*mf).cyclic_size { + (*mf).cyclic_pos = 0; + } + (*mf).read_pos += 1; + if (*mf).read_pos.wrapping_add((*mf).offset) == 4294967295 { + normalize(mf); + } +} +#[inline(always)] +unsafe fn move_pending(mf: *mut lzma_mf) { + (*mf).read_pos += 1; + (*mf).pending += 1; +} +#[inline] +unsafe fn hc_find_func( + len_limit: u32, + pos: u32, + cur: *const u8, + mut cur_match: u32, + mut depth: u32, + son: *mut u32, + cyclic_pos: u32, + cyclic_size: u32, + mut matches: *mut lzma_match, + mut len_best: u32, +) -> *mut lzma_match { + *son.offset(cyclic_pos as isize) = cur_match; + loop { + let delta: u32 = pos.wrapping_sub(cur_match); + let old_depth = depth; + depth -= 1; + if old_depth == 0 || delta >= cyclic_size { + return matches; + } + let pb: *const u8 = cur.offset(-(delta as isize)); + cur_match = *son.offset( + cyclic_pos + .wrapping_sub(delta) + .wrapping_add(if delta > cyclic_pos { cyclic_size } else { 0 }) + as isize, + ); + if *pb.offset(len_best as isize) == *cur.offset(len_best as isize) && *pb == *cur { + let len: u32 = lzma_memcmplen(pb, cur, 1, len_limit); + if len_best < len { + len_best = len; + (*matches).len = len; + (*matches).dist = delta - 1; + matches = matches.offset(1); + if len == len_limit { + return matches; + } + } + } + } +} +#[inline] +pub unsafe extern "C" fn lzma_mf_hc3_find(mf: *mut lzma_mf, matches: *mut lzma_match) -> u32 { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + } else if len_limit < 3 || false && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + return 0; + } + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let mut matches_count: u32 = 0; + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & (*mf).hash_mask; + let delta2: u32 = pos.wrapping_sub(*(*mf).hash.offset(hash_2_value as isize)); + let cur_match: u32 = *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize); + *(*mf).hash.offset(hash_2_value as isize) = pos; + *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize) = pos; + let mut len_best: u32 = 2; + if delta2 < (*mf).cyclic_size && *cur.offset(-(delta2 as isize)) == *cur { + len_best = lzma_memcmplen(cur.offset(-(delta2 as isize)), cur, len_best, len_limit); + (*matches).len = len_best; + (*matches).dist = delta2 - 1; + matches_count = 1; + if len_best == len_limit { + *(*mf).son.offset((*mf).cyclic_pos as isize) = cur_match; + move_pos(mf); + return 1; + } + } + matches_count = hc_find_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + matches.offset(matches_count as isize), + len_best, + ) + .offset_from(matches) as u32; + move_pos(mf); + matches_count +} +#[inline] +pub unsafe extern "C" fn lzma_mf_hc3_skip(mf: *mut lzma_mf, mut amount: u32) { + loop { + if mf_avail(mf) < 3 { + move_pending(mf); + } else { + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & (*mf).hash_mask; + let cur_match: u32 = *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize); + *(*mf).hash.offset(hash_2_value as isize) = pos; + *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize) = pos; + *(*mf).son.offset((*mf).cyclic_pos as isize) = cur_match; + move_pos(mf); + } + amount -= 1; + if amount == 0 { + break; + } + } +} +#[inline] +pub unsafe extern "C" fn lzma_mf_hc4_find(mf: *mut lzma_mf, matches: *mut lzma_match) -> u32 { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + } else if len_limit < 4 || false && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + return 0; + } + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let mut matches_count: u32 = 0; + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_3_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & HASH_3_MASK as u32; + let hash_value: u32 = + (temp ^ (*cur.offset(2) as u32) << 8 ^ lzma_crc32_table[0][*cur.offset(3) as usize] << 5) + & (*mf).hash_mask; + let hash = (*mf).hash; + let son = (*mf).son; + let cyclic_pos = (*mf).cyclic_pos; + let depth = (*mf).depth; + let cyclic_size = (*mf).cyclic_size; + let hash_3_index = FIX_3_HASH_SIZE as u32 + hash_3_value; + let hash_4_index = FIX_4_HASH_SIZE as u32 + hash_value; + let mut delta2: u32 = pos.wrapping_sub(*hash.offset(hash_2_value as isize)); + let delta3: u32 = pos.wrapping_sub(*hash.offset(hash_3_index as isize)); + let cur_match: u32 = *hash.offset(hash_4_index as isize); + *hash.offset(hash_2_value as isize) = pos; + *hash.offset(hash_3_index as isize) = pos; + *hash.offset(hash_4_index as isize) = pos; + let mut len_best: u32 = 1; + if delta2 < (*mf).cyclic_size && *cur.offset(-(delta2 as isize)) == *cur { + len_best = 2; + (*matches).len = 2; + (*matches).dist = delta2 - 1; + matches_count = 1; + } + if delta2 != delta3 && delta3 < (*mf).cyclic_size && *cur.offset(-(delta3 as isize)) == *cur { + len_best = 3; + (*matches.offset(matches_count as isize)).dist = delta3 - 1; + matches_count += 1; + delta2 = delta3; + } + if matches_count != 0 { + len_best = lzma_memcmplen(cur.offset(-(delta2 as isize)), cur, len_best, len_limit); + (*matches.offset((matches_count - 1) as isize)).len = len_best; + if len_best == len_limit { + *son.offset(cyclic_pos as isize) = cur_match; + move_pos(mf); + return matches_count; + } + } + if len_best < 3 { + len_best = 3; + } + matches_count = hc_find_func( + len_limit, + pos, + cur, + cur_match, + depth, + son, + cyclic_pos, + cyclic_size, + matches.offset(matches_count as isize), + len_best, + ) + .offset_from(matches) as u32; + move_pos(mf); + matches_count +} +#[inline] +pub unsafe extern "C" fn lzma_mf_hc4_skip(mf: *mut lzma_mf, mut amount: u32) { + loop { + if mf_avail(mf) < 4 { + move_pending(mf); + } else { + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_3_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & HASH_3_MASK as u32; + let hash_value: u32 = (temp + ^ (*cur.offset(2) as u32) << 8 + ^ lzma_crc32_table[0][*cur.offset(3) as usize] << 5) + & (*mf).hash_mask; + let hash = (*mf).hash; + let hash_3_index = FIX_3_HASH_SIZE as u32 + hash_3_value; + let hash_4_index = FIX_4_HASH_SIZE as u32 + hash_value; + let cur_match: u32 = *hash.offset(hash_4_index as isize); + *hash.offset(hash_2_value as isize) = pos; + *hash.offset(hash_3_index as isize) = pos; + *hash.offset(hash_4_index as isize) = pos; + *(*mf).son.offset((*mf).cyclic_pos as isize) = cur_match; + move_pos(mf); + } + amount -= 1; + if amount == 0 { + break; + } + } +} +#[inline] +unsafe fn bt_find_func( + len_limit: u32, + pos: u32, + cur: *const u8, + mut cur_match: u32, + mut depth: u32, + son: *mut u32, + cyclic_pos: u32, + cyclic_size: u32, + mut matches: *mut lzma_match, + mut len_best: u32, +) -> *mut lzma_match { + let mut ptr0: *mut u32 = son.offset((cyclic_pos << 1) as isize).offset(1); + let mut ptr1: *mut u32 = son.offset((cyclic_pos << 1) as isize); + let mut len0: u32 = 0; + let mut len1: u32 = 0; + loop { + let delta: u32 = pos - cur_match; + if depth == 0 || delta >= cyclic_size { + *ptr0 = EMPTY_HASH_VALUE; + *ptr1 = EMPTY_HASH_VALUE; + return matches; + } + depth -= 1; + let pair_index = if delta > cyclic_pos { + cyclic_pos + cyclic_size - delta + } else { + cyclic_pos - delta + }; + let pair: *mut u32 = son.offset((pair_index << 1) as isize); + let pb: *const u8 = cur.offset(-(delta as isize)); + let mut len: u32 = if len0 < len1 { len0 } else { len1 }; + if *pb.offset(len as isize) == *cur.offset(len as isize) { + len = lzma_memcmplen(pb, cur, len + 1, len_limit); + if len_best < len { + len_best = len; + (*matches).len = len; + (*matches).dist = delta - 1; + matches = matches.offset(1); + if len == len_limit { + *ptr1 = *pair; + *ptr0 = *pair.offset(1); + return matches; + } + } + } + if (*pb.offset(len as isize)) < *cur.offset(len as isize) { + *ptr1 = cur_match; + ptr1 = pair.offset(1); + cur_match = *ptr1; + len1 = len; + } else { + *ptr0 = cur_match; + ptr0 = pair; + cur_match = *ptr0; + len0 = len; + } + } +} +#[inline] +unsafe fn bt_skip_func( + len_limit: u32, + pos: u32, + cur: *const u8, + mut cur_match: u32, + mut depth: u32, + son: *mut u32, + cyclic_pos: u32, + cyclic_size: u32, +) { + let mut ptr0: *mut u32 = son.offset((cyclic_pos << 1) as isize).offset(1); + let mut ptr1: *mut u32 = son.offset((cyclic_pos << 1) as isize); + let mut len0: u32 = 0; + let mut len1: u32 = 0; + loop { + let delta: u32 = pos - cur_match; + if depth == 0 || delta >= cyclic_size { + *ptr0 = EMPTY_HASH_VALUE; + *ptr1 = EMPTY_HASH_VALUE; + return; + } + depth -= 1; + let pair_index = if delta > cyclic_pos { + cyclic_pos + cyclic_size - delta + } else { + cyclic_pos - delta + }; + let pair: *mut u32 = son.offset((pair_index << 1) as isize); + let pb: *const u8 = cur.offset(-(delta as isize)); + let mut len: u32 = if len0 < len1 { len0 } else { len1 }; + if *pb.offset(len as isize) == *cur.offset(len as isize) { + len = lzma_memcmplen(pb, cur, len + 1, len_limit); + if len == len_limit { + *ptr1 = *pair; + *ptr0 = *pair.offset(1); + return; + } + } + if (*pb.offset(len as isize)) < *cur.offset(len as isize) { + *ptr1 = cur_match; + ptr1 = pair.offset(1); + cur_match = *ptr1; + len1 = len; + } else { + *ptr0 = cur_match; + ptr0 = pair; + cur_match = *ptr0; + len0 = len; + } + } +} +#[inline] +pub unsafe extern "C" fn lzma_mf_bt2_find(mf: *mut lzma_mf, matches: *mut lzma_match) -> u32 { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + } else if len_limit < 2 || true && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + return 0; + } + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let mut matches_count: u32 = 0; + let hash_value: u32 = *cur as u32 | (*cur.offset(1) as u32) << 8; + let cur_match: u32 = *(*mf).hash.offset(hash_value as isize); + *(*mf).hash.offset(hash_value as isize) = pos; + matches_count = bt_find_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + matches.offset(matches_count as isize), + 1, + ) + .offset_from(matches) as u32; + move_pos(mf); + matches_count +} +#[inline] +pub unsafe extern "C" fn lzma_mf_bt2_skip(mf: *mut lzma_mf, mut amount: u32) { + let mut current_block_8: u64; + loop { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + current_block_8 = 11875828834189669668; + } else if len_limit < 2 || true && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + current_block_8 = 18088007599891946824; + } else { + current_block_8 = 11875828834189669668; + } + match current_block_8 { + 11875828834189669668 => { + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let hash_value: u32 = *cur as u32 | (*cur.offset(1) as u32) << 8; + let cur_match: u32 = *(*mf).hash.offset(hash_value as isize); + *(*mf).hash.offset(hash_value as isize) = pos; + bt_skip_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + ); + move_pos(mf); + } + _ => {} + } + amount -= 1; + if amount == 0 { + break; + } + } +} +#[inline] +pub unsafe extern "C" fn lzma_mf_bt3_find(mf: *mut lzma_mf, matches: *mut lzma_match) -> u32 { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + } else if len_limit < 3 || true && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + return 0; + } + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let mut matches_count: u32 = 0; + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & (*mf).hash_mask; + let delta2: u32 = pos.wrapping_sub(*(*mf).hash.offset(hash_2_value as isize)); + let cur_match: u32 = *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize); + *(*mf).hash.offset(hash_2_value as isize) = pos; + *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize) = pos; + let mut len_best: u32 = 2; + if delta2 < (*mf).cyclic_size && *cur.offset(-(delta2 as isize)) == *cur { + len_best = lzma_memcmplen(cur, cur.offset(-(delta2 as isize)), len_best, len_limit); + (*matches).len = len_best; + (*matches).dist = delta2 - 1; + matches_count = 1; + if len_best == len_limit { + bt_skip_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + ); + move_pos(mf); + return 1; + } + } + matches_count = bt_find_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + matches.offset(matches_count as isize), + len_best, + ) + .offset_from(matches) as u32; + move_pos(mf); + matches_count +} +#[inline] +pub unsafe extern "C" fn lzma_mf_bt3_skip(mf: *mut lzma_mf, mut amount: u32) { + let mut current_block_9: u64; + loop { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + current_block_9 = 11875828834189669668; + } else if len_limit < 3 || true && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + current_block_9 = 18088007599891946824; + } else { + current_block_9 = 11875828834189669668; + } + match current_block_9 { + 11875828834189669668 => { + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & (*mf).hash_mask; + let cur_match: u32 = *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize); + *(*mf).hash.offset(hash_2_value as isize) = pos; + *(*mf) + .hash + .offset((FIX_3_HASH_SIZE as u32 + hash_value) as isize) = pos; + bt_skip_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + ); + move_pos(mf); + } + _ => {} + } + amount -= 1; + if amount == 0 { + break; + } + } +} +#[inline] +pub unsafe extern "C" fn lzma_mf_bt4_find(mf: *mut lzma_mf, matches: *mut lzma_match) -> u32 { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + } else if len_limit < 4 || true && (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + return 0; + } + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let mut matches_count: u32 = 0; + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_3_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & HASH_3_MASK as u32; + let hash_value: u32 = + (temp ^ (*cur.offset(2) as u32) << 8 ^ lzma_crc32_table[0][*cur.offset(3) as usize] << 5) + & (*mf).hash_mask; + let hash_3_index = FIX_3_HASH_SIZE as u32 + hash_3_value; + let hash_4_index = FIX_4_HASH_SIZE as u32 + hash_value; + let mut delta2: u32 = pos - *(*mf).hash.offset(hash_2_value as isize); + let delta3: u32 = pos - *(*mf).hash.offset(hash_3_index as isize); + let cur_match: u32 = *(*mf).hash.offset(hash_4_index as isize); + *(*mf).hash.offset(hash_2_value as isize) = pos; + *(*mf).hash.offset(hash_3_index as isize) = pos; + *(*mf).hash.offset(hash_4_index as isize) = pos; + let mut len_best: u32 = 1; + if delta2 < (*mf).cyclic_size && *cur.offset(-(delta2 as isize)) == *cur { + len_best = 2; + (*matches).len = 2; + (*matches).dist = delta2 - 1; + matches_count = 1; + } + if delta2 != delta3 && delta3 < (*mf).cyclic_size && *cur.offset(-(delta3 as isize)) == *cur { + len_best = 3; + (*matches.offset(matches_count as isize)).dist = delta3 - 1; + matches_count += 1; + delta2 = delta3; + } + if matches_count != 0 { + len_best = lzma_memcmplen(cur, cur.offset(-(delta2 as isize)), len_best, len_limit); + (*matches.offset((matches_count - 1) as isize)).len = len_best; + if len_best == len_limit { + bt_skip_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + ); + move_pos(mf); + return matches_count; + } + } + if len_best < 3 { + len_best = 3; + } + matches_count = bt_find_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + matches.offset(matches_count as isize), + len_best, + ) + .offset_from(matches) as u32; + move_pos(mf); + matches_count +} +#[inline] +pub unsafe extern "C" fn lzma_mf_bt4_skip(mf: *mut lzma_mf, mut amount: u32) { + debug_assert!(amount > 0); + loop { + let mut len_limit: u32 = mf_avail(mf); + if (*mf).nice_len <= len_limit { + len_limit = (*mf).nice_len; + } else if len_limit < 4 || (*mf).action == LZMA_SYNC_FLUSH { + move_pending(mf); + amount -= 1; + if amount == 0 { + break; + } + continue; + } + + let cur: *const u8 = mf_ptr(mf); + let pos: u32 = (*mf).read_pos.wrapping_add((*mf).offset); + let temp: u32 = lzma_crc32_table[0][*cur as usize] ^ *cur.offset(1) as u32; + let hash_2_value: u32 = temp & HASH_2_MASK as u32; + let hash_3_value: u32 = (temp ^ (*cur.offset(2) as u32) << 8) & HASH_3_MASK as u32; + let hash_value: u32 = (temp + ^ (*cur.offset(2) as u32) << 8 + ^ lzma_crc32_table[0][*cur.offset(3) as usize] << 5) + & (*mf).hash_mask; + let hash_3_index = FIX_3_HASH_SIZE as u32 + hash_3_value; + let hash_4_index = FIX_4_HASH_SIZE as u32 + hash_value; + let cur_match: u32 = *(*mf).hash.offset(hash_4_index as isize); + + *(*mf).hash.offset(hash_2_value as isize) = pos; + *(*mf).hash.offset(hash_3_index as isize) = pos; + *(*mf).hash.offset(hash_4_index as isize) = pos; + + bt_skip_func( + len_limit, + pos, + cur, + cur_match, + (*mf).depth, + (*mf).son, + (*mf).cyclic_pos, + (*mf).cyclic_size, + ); + move_pos(mf); + + amount -= 1; + if amount == 0 { + break; + } + } +} diff --git a/liblzma-rs/src/lz/mod.rs b/liblzma-rs/src/lz/mod.rs new file mode 100644 index 00000000..e835f7fc --- /dev/null +++ b/liblzma-rs/src/lz/mod.rs @@ -0,0 +1,3 @@ +pub mod lz_decoder; +pub mod lz_encoder; +pub mod lz_encoder_mf; diff --git a/liblzma-rs/src/lzma/fastpos_table.rs b/liblzma-rs/src/lzma/fastpos_table.rs new file mode 100644 index 00000000..db50e825 --- /dev/null +++ b/liblzma-rs/src/lzma/fastpos_table.rs @@ -0,0 +1,343 @@ +pub static mut lzma_fastpos: [u8; 8192] = [ + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +]; diff --git a/liblzma-rs/src/lzma/lzma2_decoder.rs b/liblzma-rs/src/lzma/lzma2_decoder.rs new file mode 100644 index 00000000..8c2efd29 --- /dev/null +++ b/liblzma-rs/src/lzma/lzma2_decoder.rs @@ -0,0 +1,290 @@ +use crate::lz::lz_decoder::{lzma_lz_decoder_init, lzma_lz_options}; +use crate::lzma::lzma_decoder::lzma_lzma_decoder_create; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lzma2_coder { + pub sequence: sequence, + pub next_sequence: sequence, + pub lzma: lzma_lz_decoder, + pub uncompressed_size: size_t, + pub compressed_size: size_t, + pub need_properties: bool, + pub need_dictionary_reset: bool, + pub options: lzma_options_lzma, +} +pub type sequence = c_uint; +pub const SEQ_COPY: sequence = 7; +pub const SEQ_LZMA: sequence = 6; +pub const SEQ_PROPERTIES: sequence = 5; +pub const SEQ_COMPRESSED_1: sequence = 4; +pub const SEQ_COMPRESSED_0: sequence = 3; +pub const SEQ_UNCOMPRESSED_2: sequence = 2; +pub const SEQ_UNCOMPRESSED_1: sequence = 1; +pub const SEQ_CONTROL: sequence = 0; +pub const LZMA_LZ_DECODER_INIT: lzma_lz_decoder = lzma_lz_decoder { + coder: core::ptr::null_mut(), + code: None, + reset: None, + set_uncompressed: None, + end: None, +}; +#[inline] +unsafe fn dict_write( + dict: *mut lzma_dict, + in_0: *const u8, + in_pos: *mut size_t, + mut in_size: size_t, + left: *mut size_t, +) { + if in_size.wrapping_sub(*in_pos) > *left { + in_size = (*in_pos).wrapping_add(*left); + } + *left = (*left).wrapping_sub(lzma_bufcpy( + in_0, + in_pos, + in_size, + (*dict).buf, + ::core::ptr::addr_of_mut!((*dict).pos), + (*dict).limit, + )); + if !(*dict).has_wrapped { + (*dict).full = (*dict).pos.wrapping_sub(LZ_DICT_INIT_POS as size_t); + } +} +#[inline] +unsafe fn dict_reset(dict: *mut lzma_dict) { + (*dict).need_reset = true; +} +unsafe extern "C" fn lzma2_decode( + coder_ptr: *mut c_void, + dict: *mut lzma_dict, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; + while *in_pos < in_size || (*coder).sequence == SEQ_LZMA { + match (*coder).sequence { + 0 => { + let control: u32 = *in_0.offset(*in_pos as isize) as u32; + *in_pos = (*in_pos).wrapping_add(1); + if control == 0 { + return LZMA_STREAM_END; + } + if control >= 0xe0 || control == 1 { + (*coder).need_properties = true; + (*coder).need_dictionary_reset = true; + } else if (*coder).need_dictionary_reset { + return LZMA_DATA_ERROR; + } + if control >= 0x80 { + (*coder).uncompressed_size = ((control & 0x1f) << 16) as size_t; + (*coder).sequence = SEQ_UNCOMPRESSED_1; + if control >= 0xc0 { + (*coder).need_properties = false; + (*coder).next_sequence = SEQ_PROPERTIES; + } else if (*coder).need_properties { + return LZMA_DATA_ERROR; + } else { + (*coder).next_sequence = SEQ_LZMA; + if control >= 0xa0 { + (*coder).lzma.reset.unwrap()( + (*coder).lzma.coder, + ::core::ptr::addr_of_mut!((*coder).options) as *const c_void, + ); + } + } + } else { + if control > 2 { + return LZMA_DATA_ERROR; + } + (*coder).sequence = SEQ_COMPRESSED_0; + (*coder).next_sequence = SEQ_COPY; + } + if (*coder).need_dictionary_reset { + (*coder).need_dictionary_reset = false; + dict_reset(dict); + return LZMA_OK; + } + } + 1 => { + (*coder).uncompressed_size = (*coder) + .uncompressed_size + .wrapping_add(((*in_0.offset(*in_pos as isize) as u32) << 8) as size_t); + *in_pos += 1; + (*coder).sequence = SEQ_UNCOMPRESSED_2; + } + 2 => { + (*coder).uncompressed_size = (*coder).uncompressed_size.wrapping_add( + u32::from(*in_0.offset(*in_pos as isize)).wrapping_add(1) as size_t, + ); + *in_pos += 1; + (*coder).sequence = SEQ_COMPRESSED_0; + (*coder).lzma.set_uncompressed.unwrap()( + (*coder).lzma.coder, + (*coder).uncompressed_size as lzma_vli, + false, + ); + } + 3 => { + (*coder).compressed_size = ((*in_0.offset(*in_pos as isize) as u32) << 8) as size_t; + *in_pos += 1; + (*coder).sequence = SEQ_COMPRESSED_1; + } + 4 => { + (*coder).compressed_size = (*coder).compressed_size.wrapping_add( + u32::from(*in_0.offset(*in_pos as isize)).wrapping_add(1) as size_t, + ); + *in_pos += 1; + (*coder).sequence = (*coder).next_sequence as sequence; + } + 5 => { + let prop_byte = *in_0.offset(*in_pos as isize); + *in_pos += 1; + if lzma_lzma_lclppb_decode(::core::ptr::addr_of_mut!((*coder).options), prop_byte) { + return LZMA_DATA_ERROR; + } + (*coder).lzma.reset.unwrap()( + (*coder).lzma.coder, + ::core::ptr::addr_of_mut!((*coder).options) as *const c_void, + ); + (*coder).sequence = SEQ_LZMA; + } + 6 => { + let in_start: size_t = *in_pos; + let ret: lzma_ret = + (*coder).lzma.code.unwrap()((*coder).lzma.coder, dict, in_0, in_pos, in_size); + let in_used: size_t = (*in_pos).wrapping_sub(in_start); + if in_used > (*coder).compressed_size { + return LZMA_DATA_ERROR; + } + (*coder).compressed_size = (*coder).compressed_size.wrapping_sub(in_used); + if ret != LZMA_STREAM_END { + return ret; + } + if (*coder).compressed_size != 0 { + return LZMA_DATA_ERROR; + } + (*coder).sequence = SEQ_CONTROL; + } + 7 => { + dict_write( + dict, + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).compressed_size), + ); + if (*coder).compressed_size != 0 { + return LZMA_OK; + } + (*coder).sequence = SEQ_CONTROL; + } + _ => return LZMA_PROG_ERROR, + } + } + LZMA_OK +} +unsafe extern "C" fn lzma2_decoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; + crate::alloc::internal_free((*coder).lzma.coder, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn lzma2_decoder_init( + lz: *mut lzma_lz_decoder, + allocator: *const lzma_allocator, + _id: lzma_vli, + opt: *const c_void, + lz_options: *mut lzma_lz_options, +) -> lzma_ret { + let mut coder: *mut lzma_lzma2_coder = (*lz).coder as *mut lzma_lzma2_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*lz).coder = coder as *mut c_void; + (*lz).code = Some( + lzma2_decode + as unsafe extern "C" fn( + *mut c_void, + *mut lzma_dict, + *const u8, + *mut size_t, + size_t, + ) -> lzma_ret, + ); + (*lz).end = Some( + lzma2_decoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*coder).lzma = LZMA_LZ_DECODER_INIT; + } + let options: *const lzma_options_lzma = opt as *const lzma_options_lzma; + (*coder).sequence = SEQ_CONTROL; + (*coder).need_properties = true; + (*coder).need_dictionary_reset = + (*options).preset_dict.is_null() || (*options).preset_dict_size == 0; + lzma_lzma_decoder_create( + ::core::ptr::addr_of_mut!((*coder).lzma), + allocator, + options, + lz_options, + ) +} +pub unsafe extern "C" fn lzma_lzma2_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + lzma_lz_decoder_init( + next, + allocator, + filters, + Some( + lzma2_decoder_init + as unsafe extern "C" fn( + *mut lzma_lz_decoder, + *const lzma_allocator, + lzma_vli, + *const c_void, + *mut lzma_lz_options, + ) -> lzma_ret, + ), + ) +} +pub extern "C" fn lzma_lzma2_decoder_memusage(options: *const c_void) -> u64 { + (core::mem::size_of::() as u64) + .wrapping_add(lzma_lzma_decoder_memusage_nocheck(options)) +} +pub unsafe extern "C" fn lzma_lzma2_props_decode( + options: *mut *mut c_void, + allocator: *const lzma_allocator, + props: *const u8, + props_size: size_t, +) -> lzma_ret { + if props_size != 1 { + return LZMA_OPTIONS_ERROR; + } + if *props & 0xc0 != 0 { + return LZMA_OPTIONS_ERROR; + } + if *props > 40 { + return LZMA_OPTIONS_ERROR; + } + let opt: *mut lzma_options_lzma = + lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_options_lzma; + if opt.is_null() { + return LZMA_MEM_ERROR; + } + if *props == 40 { + (*opt).dict_size = UINT32_MAX; + } else { + (*opt).dict_size = 2u32 | (u32::from(*props) & 1); + (*opt).dict_size <<= u32::from(*props).wrapping_div(2).wrapping_add(11); + } + (*opt).preset_dict = core::ptr::null(); + (*opt).preset_dict_size = 0; + *options = opt as *mut c_void; + LZMA_OK +} diff --git a/liblzma-rs/src/lzma/lzma2_encoder.rs b/liblzma-rs/src/lzma/lzma2_encoder.rs new file mode 100644 index 00000000..5b64b54f --- /dev/null +++ b/liblzma-rs/src/lzma/lzma2_encoder.rs @@ -0,0 +1,395 @@ +use crate::lz::lz_encoder::{lzma_lz_encoder_init, lzma_lz_options}; +use crate::lzma::lzma_encoder::{ + lzma_lzma_encode, lzma_lzma_encoder_create, lzma_lzma_encoder_reset, +}; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lzma2_coder { + pub sequence: lzma2_encoder_seq, + pub lzma: *mut c_void, + pub opt_cur: lzma_options_lzma, + pub need_properties: bool, + pub need_state_reset: bool, + pub need_dictionary_reset: bool, + pub uncompressed_size: size_t, + pub compressed_size: size_t, + pub buf_pos: size_t, + pub buf: [u8; 65542], +} +pub type lzma2_encoder_seq = c_uint; +pub const SEQ_UNCOMPRESSED_COPY: lzma2_encoder_seq = 4; +pub const SEQ_UNCOMPRESSED_HEADER: lzma2_encoder_seq = 3; +pub const SEQ_LZMA_COPY: lzma2_encoder_seq = 2; +pub const SEQ_LZMA_ENCODE: lzma2_encoder_seq = 1; +pub const SEQ_INIT: lzma2_encoder_seq = 0; +#[inline] +unsafe fn mf_unencoded(mf: *const lzma_mf) -> u32 { + (*mf).write_pos - (*mf).read_pos + (*mf).read_ahead +} +#[inline] +unsafe fn mf_read( + mf: *mut lzma_mf, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + left: *mut size_t, +) { + let out_avail: size_t = out_size - *out_pos; + let copy_size: size_t = if out_avail < *left { out_avail } else { *left }; + core::ptr::copy_nonoverlapping( + (*mf) + .buffer + .offset((*mf).read_pos as isize) + .offset(-(*left as isize)) as *const u8, + out.offset(*out_pos as isize) as *mut u8, + copy_size, + ); + *out_pos += copy_size; + *left -= copy_size; +} +pub const LZMA2_UNCOMPRESSED_MAX: c_uint = 1u32 << 21; +pub const LZMA2_HEADER_MAX: u32 = 6; +unsafe fn lzma2_header_lzma(coder: *mut lzma_lzma2_coder) { + let mut pos: size_t = 0; + if (*coder).need_properties { + pos = 0; + if (*coder).need_dictionary_reset { + (*coder).buf[pos as usize] = (0x80 + ((3) << 5)) as u8; + } else { + (*coder).buf[pos as usize] = (0x80 + ((2) << 5)) as u8; + } + } else { + pos = 1; + if (*coder).need_state_reset { + (*coder).buf[pos as usize] = (0x80 + (1 << 5)) as u8; + } else { + (*coder).buf[pos as usize] = 0x80 as u8; + } + } + (*coder).buf_pos = pos; + let mut size: size_t = (*coder).uncompressed_size - 1; + (*coder).buf[pos as usize] = ((*coder).buf[pos as usize] as size_t + (size >> 16)) as u8; + pos += 1; + (*coder).buf[pos as usize] = (size >> 8 & 0xff) as u8; + pos += 1; + (*coder).buf[pos as usize] = (size & 0xff) as u8; + pos += 1; + size = (*coder).compressed_size - 1; + (*coder).buf[pos as usize] = (size >> 8) as u8; + pos += 1; + (*coder).buf[pos as usize] = (size & 0xff) as u8; + pos += 1; + if (*coder).need_properties { + lzma_lzma_lclppb_encode( + ::core::ptr::addr_of_mut!((*coder).opt_cur), + (::core::ptr::addr_of_mut!((*coder).buf) as *mut u8).offset(pos as isize), + ); + } + (*coder).need_properties = false; + (*coder).need_state_reset = false; + (*coder).need_dictionary_reset = false; + (*coder).compressed_size += LZMA2_HEADER_MAX as size_t; +} +unsafe fn lzma2_header_uncompressed(coder: *mut lzma_lzma2_coder) { + if (*coder).need_dictionary_reset { + (*coder).buf[0] = 1; + } else { + (*coder).buf[0] = 2; + } + (*coder).need_dictionary_reset = false; + (*coder).buf[1] = ((*coder).uncompressed_size - 1 >> 8) as u8; + (*coder).buf[2] = ((*coder).uncompressed_size - 1 & 0xff) as u8; + (*coder).buf_pos = 0; +} +unsafe extern "C" fn lzma2_encode( + coder_ptr: *mut c_void, + mf: *mut lzma_mf, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; + while *out_pos < out_size { + let mut current_block_45: u64; + match (*coder).sequence { + 0 => { + if mf_unencoded(mf) == 0 { + if (*mf).action == LZMA_FINISH { + *out.offset(*out_pos as isize) = 0; + *out_pos += 1; + } + return if (*mf).action == LZMA_RUN { + LZMA_OK + } else { + LZMA_STREAM_END + }; + } + if (*coder).need_state_reset { + let ret_: lzma_ret = lzma_lzma_encoder_reset( + (*coder).lzma as *mut lzma_lzma1_encoder, + ::core::ptr::addr_of_mut!((*coder).opt_cur), + ); + if ret_ != LZMA_OK { + return ret_; + } + } + (*coder).uncompressed_size = 0; + (*coder).compressed_size = 0; + (*coder).sequence = SEQ_LZMA_ENCODE; + current_block_45 = 2979737022853876585; + } + 1 => { + current_block_45 = 2979737022853876585; + } + 2 => { + current_block_45 = 13410404938545238636; + } + 3 => { + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).buf) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).buf_pos), + LZMA2_HEADER_UNCOMPRESSED as size_t, + out, + out_pos, + out_size, + ); + if (*coder).buf_pos != LZMA2_HEADER_UNCOMPRESSED as size_t { + return LZMA_OK; + } + (*coder).sequence = SEQ_UNCOMPRESSED_COPY; + current_block_45 = 10903800704467975402; + } + 4 => { + current_block_45 = 10903800704467975402; + } + _ => { + current_block_45 = 11743904203796629665; + } + } + match current_block_45 { + 10903800704467975402 => { + mf_read( + mf, + out, + out_pos, + out_size, + ::core::ptr::addr_of_mut!((*coder).uncompressed_size), + ); + if (*coder).uncompressed_size != 0 { + return LZMA_OK; + } + (*coder).sequence = SEQ_INIT; + current_block_45 = 11743904203796629665; + } + 2979737022853876585 => { + let left: u32 = + ((LZMA2_UNCOMPRESSED_MAX as size_t) - (*coder).uncompressed_size) as u32; + let mut limit: u32 = 0; + if left < (*mf).match_len_max { + limit = 0; + } else { + limit = (*mf).read_pos - (*mf).read_ahead + left - (*mf).match_len_max; + } + let read_start: u32 = (*mf).read_pos - (*mf).read_ahead; + let ret: lzma_ret = lzma_lzma_encode( + (*coder).lzma as *mut lzma_lzma1_encoder, + mf, + (::core::ptr::addr_of_mut!((*coder).buf) as *mut u8) + .offset(LZMA2_HEADER_MAX as isize), + ::core::ptr::addr_of_mut!((*coder).compressed_size), + LZMA2_CHUNK_MAX as size_t, + limit, + ); + (*coder).uncompressed_size += + ((*mf).read_pos - (*mf).read_ahead - read_start) as size_t; + if ret != LZMA_STREAM_END { + return LZMA_OK; + } + if (*coder).compressed_size >= (*coder).uncompressed_size { + (*coder).uncompressed_size += (*mf).read_ahead as size_t; + (*mf).read_ahead = 0; + lzma2_header_uncompressed(coder); + (*coder).need_state_reset = true; + (*coder).sequence = SEQ_UNCOMPRESSED_HEADER; + current_block_45 = 11743904203796629665; + } else { + lzma2_header_lzma(coder); + (*coder).sequence = SEQ_LZMA_COPY; + current_block_45 = 13410404938545238636; + } + } + _ => {} + } + match current_block_45 { + 13410404938545238636 => { + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).buf) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).buf_pos), + (*coder).compressed_size, + out, + out_pos, + out_size, + ); + if (*coder).buf_pos != (*coder).compressed_size { + return LZMA_OK; + } + (*coder).sequence = SEQ_INIT; + } + _ => {} + } + } + LZMA_OK +} +unsafe extern "C" fn lzma2_encoder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; + crate::alloc::internal_free((*coder).lzma, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn lzma2_encoder_options_update( + coder_ptr: *mut c_void, + filter: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_lzma2_coder = coder_ptr as *mut lzma_lzma2_coder; + if (*filter).options.is_null() || (*coder).sequence != SEQ_INIT { + return LZMA_PROG_ERROR; + } + let opt: *const lzma_options_lzma = (*filter).options as *const lzma_options_lzma; + if (*coder).opt_cur.lc != (*opt).lc + || (*coder).opt_cur.lp != (*opt).lp + || (*coder).opt_cur.pb != (*opt).pb + { + if (*opt).lc > LZMA_LCLP_MAX + || (*opt).lp > LZMA_LCLP_MAX + || (*opt).lc + (*opt).lp > LZMA_LCLP_MAX + || (*opt).pb > LZMA_PB_MAX + { + return LZMA_OPTIONS_ERROR; + } + (*coder).opt_cur.lc = (*opt).lc; + (*coder).opt_cur.lp = (*opt).lp; + (*coder).opt_cur.pb = (*opt).pb; + (*coder).need_properties = true; + (*coder).need_state_reset = true; + } + LZMA_OK +} +unsafe extern "C" fn lzma2_encoder_init( + lz: *mut lzma_lz_encoder, + allocator: *const lzma_allocator, + _id: lzma_vli, + options: *const c_void, + lz_options: *mut lzma_lz_options, +) -> lzma_ret { + if options.is_null() { + return LZMA_PROG_ERROR; + } + let mut coder: *mut lzma_lzma2_coder = (*lz).coder as *mut lzma_lzma2_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_object::(allocator); + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*lz).coder = coder as *mut c_void; + (*lz).code = Some( + lzma2_encode + as unsafe extern "C" fn( + *mut c_void, + *mut lzma_mf, + *mut u8, + *mut size_t, + size_t, + ) -> lzma_ret, + ); + (*lz).end = Some( + lzma2_encoder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*lz).options_update = Some( + lzma2_encoder_options_update + as unsafe extern "C" fn(*mut c_void, *const lzma_filter) -> lzma_ret, + ); + (*coder).lzma = core::ptr::null_mut(); + } + (*coder).opt_cur = *(options as *const lzma_options_lzma); + (*coder).sequence = SEQ_INIT; + (*coder).need_properties = true; + (*coder).need_state_reset = false; + (*coder).need_dictionary_reset = + (*coder).opt_cur.preset_dict.is_null() || (*coder).opt_cur.preset_dict_size == 0; + let ret_: lzma_ret = lzma_lzma_encoder_create( + ::core::ptr::addr_of_mut!((*coder).lzma), + allocator, + 0x21, + ::core::ptr::addr_of_mut!((*coder).opt_cur), + lz_options, + ); + if ret_ != LZMA_OK { + return ret_; + } + if (*lz_options).before_size + (*lz_options).dict_size < LZMA2_CHUNK_MAX as size_t { + (*lz_options).before_size = (LZMA2_CHUNK_MAX as size_t) - (*lz_options).dict_size; + } + LZMA_OK +} +pub unsafe extern "C" fn lzma_lzma2_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + lzma_lz_encoder_init( + next, + allocator, + filters, + Some( + lzma2_encoder_init + as unsafe extern "C" fn( + *mut lzma_lz_encoder, + *const lzma_allocator, + lzma_vli, + *const c_void, + *mut lzma_lz_options, + ) -> lzma_ret, + ), + ) +} +pub extern "C" fn lzma_lzma2_encoder_memusage(options: *const c_void) -> u64 { + let lzma_mem: u64 = lzma_lzma_encoder_memusage(options) as u64; + if lzma_mem == UINT64_MAX { + return UINT64_MAX; + } + (core::mem::size_of::() as u64) + lzma_mem +} +pub unsafe extern "C" fn lzma_lzma2_props_encode(options: *const c_void, out: *mut u8) -> lzma_ret { + if options.is_null() { + return LZMA_PROG_ERROR; + } + let opt: *const lzma_options_lzma = options as *const lzma_options_lzma; + let mut d: u32 = if (*opt).dict_size > 4096 { + (*opt).dict_size + } else { + 4096 + }; + d -= 1; + d |= d >> 2; + d |= d >> 3; + d |= d >> 4; + d |= d >> 8; + d |= d >> 16; + if d == UINT32_MAX { + *out = 40; + } else { + *out = (get_dist_slot(d + 1) - 24) as u8; + } + LZMA_OK +} +pub unsafe extern "C" fn lzma_lzma2_block_size(options: *const c_void) -> u64 { + let opt: *const lzma_options_lzma = options as *const lzma_options_lzma; + if (*opt).dict_size < LZMA_DICT_SIZE_MIN as u32 || (*opt).dict_size > (1u32 << 30) + (1 << 29) { + return UINT64_MAX; + } + if ((*opt).dict_size as u64) * 3 > 1 << 20 { + ((*opt).dict_size as u64) * 3 + } else { + 1 << 20 + } +} diff --git a/liblzma-rs/src/lzma/lzma_decoder.rs b/liblzma-rs/src/lzma/lzma_decoder.rs new file mode 100644 index 00000000..18ee3558 --- /dev/null +++ b/liblzma-rs/src/lzma/lzma_decoder.rs @@ -0,0 +1,3457 @@ +use crate::lz::lz_decoder::{lzma_lz_decoder_init, lzma_lz_decoder_memusage, lzma_lz_options}; +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lzma1_decoder { + pub literal: [probability; 12288], + pub is_match: [[probability; 16]; 12], + pub is_rep: [probability; 12], + pub is_rep0: [probability; 12], + pub is_rep1: [probability; 12], + pub is_rep2: [probability; 12], + pub is_rep0_long: [[probability; 16]; 12], + pub dist_slot: [[probability; 64]; 4], + pub pos_special: [probability; 114], + pub pos_align: [probability; 16], + pub match_len_decoder: lzma_length_decoder, + pub rep_len_decoder: lzma_length_decoder, + pub rc: lzma_range_decoder, + pub state: lzma_lzma_state, + pub rep0: u32, + pub rep1: u32, + pub rep2: u32, + pub rep3: u32, + pub pos_mask: u32, + pub literal_context_bits: u32, + pub literal_mask: u32, + pub uncompressed_size: lzma_vli, + pub allow_eopm: bool, + pub sequence: lzma_decoder_seq, + pub probs: *mut probability, + pub symbol: u32, + pub limit: u32, + pub offset: u32, + pub len: u32, +} +pub type lzma_decoder_seq = c_uint; +pub const SEQ_COPY: lzma_decoder_seq = 22; +pub const SEQ_REP_LEN_BITTREE: lzma_decoder_seq = 21; +pub const SEQ_REP_LEN_CHOICE2: lzma_decoder_seq = 20; +pub const SEQ_REP_LEN_CHOICE: lzma_decoder_seq = 19; +pub const SEQ_IS_REP2: lzma_decoder_seq = 18; +pub const SEQ_IS_REP1: lzma_decoder_seq = 17; +pub const SEQ_IS_REP0_LONG: lzma_decoder_seq = 16; +pub const SEQ_SHORTREP: lzma_decoder_seq = 15; +pub const SEQ_IS_REP0: lzma_decoder_seq = 14; +pub const SEQ_EOPM: lzma_decoder_seq = 13; +pub const SEQ_ALIGN: lzma_decoder_seq = 12; +pub const SEQ_DIRECT: lzma_decoder_seq = 11; +pub const SEQ_DIST_MODEL: lzma_decoder_seq = 10; +pub const SEQ_DIST_SLOT: lzma_decoder_seq = 9; +pub const SEQ_MATCH_LEN_BITTREE: lzma_decoder_seq = 8; +pub const SEQ_MATCH_LEN_CHOICE2: lzma_decoder_seq = 7; +pub const SEQ_MATCH_LEN_CHOICE: lzma_decoder_seq = 6; +pub const SEQ_IS_REP: lzma_decoder_seq = 5; +pub const SEQ_LITERAL_WRITE: lzma_decoder_seq = 4; +pub const SEQ_LITERAL_MATCHED: lzma_decoder_seq = 3; +pub const SEQ_LITERAL: lzma_decoder_seq = 2; +pub const SEQ_IS_MATCH: lzma_decoder_seq = 1; +pub const SEQ_NORMALIZE: lzma_decoder_seq = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_range_decoder { + pub range: u32, + pub code: u32, + pub init_bytes_left: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_length_decoder { + pub choice: probability, + pub choice2: probability, + pub low: [[probability; 8]; 16], + pub mid: [[probability; 8]; 16], + pub high: [probability; 256], +} +#[inline] +unsafe fn dict_get(dict: *const lzma_dict, distance: u32) -> u8 { + *(*dict).buf.offset( + (*dict) + .pos + .wrapping_sub(distance as size_t) + .wrapping_sub(1) + .wrapping_add(if (distance as size_t) < (*dict).pos { + 0 + } else { + (*dict).size.wrapping_sub(LZ_DICT_REPEAT_MAX as size_t) + }) as isize, + ) +} +#[inline] +unsafe fn dict_get0(dict: *const lzma_dict) -> u8 { + *(*dict).buf.offset((*dict).pos.wrapping_sub(1) as isize) +} +#[inline] +unsafe fn dict_is_distance_valid(dict: *const lzma_dict, distance: size_t) -> bool { + (*dict).full > distance +} +#[inline] +unsafe fn dict_repeat(dict: *mut lzma_dict, distance: u32, len: *mut u32) -> bool { + let dict_avail: size_t = (*dict).limit.wrapping_sub((*dict).pos); + let mut left: u32 = (if dict_avail < *len as size_t { + dict_avail + } else { + *len as size_t + }) as u32; + *len = (*len).wrapping_sub(left); + let mut back: size_t = (*dict).pos.wrapping_sub(distance as size_t).wrapping_sub(1); + if distance as size_t >= (*dict).pos { + back = back.wrapping_add((*dict).size.wrapping_sub(LZ_DICT_REPEAT_MAX as size_t)); + } + if distance < left { + loop { + *(*dict).buf.offset((*dict).pos as isize) = *(*dict).buf.offset(back as isize); + back += 1; + (*dict).pos = (*dict).pos.wrapping_add(1); + left -= 1; + if left == 0 { + break; + } + } + } else { + core::ptr::copy_nonoverlapping( + (*dict).buf.offset(back as isize) as *const u8, + (*dict).buf.offset((*dict).pos as isize) as *mut u8, + left as size_t, + ); + (*dict).pos = (*dict).pos.wrapping_add(left as size_t); + } + if !(*dict).has_wrapped { + (*dict).full = (*dict).pos.wrapping_sub(LZ_DICT_INIT_POS as size_t); + } + *len != 0 +} +#[inline] +unsafe fn dict_put(dict: *mut lzma_dict, byte: u8) { + *(*dict).buf.offset((*dict).pos as isize) = byte; + (*dict).pos = (*dict).pos.wrapping_add(1); + if !(*dict).has_wrapped { + (*dict).full = (*dict).pos.wrapping_sub(LZ_DICT_INIT_POS as size_t); + } +} +#[inline] +unsafe fn dict_put_safe(dict: *mut lzma_dict, byte: u8) -> bool { + if (*dict).pos == (*dict).limit { + return true; + } + dict_put(dict, byte); + false +} +pub const DIST_SLOTS: u32 = 1 << DIST_SLOT_BITS; +#[inline] +unsafe fn rc_read_init( + rc: *mut lzma_range_decoder, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + while (*rc).init_bytes_left > 0 { + if *in_pos == in_size { + return LZMA_OK; + } + if (*rc).init_bytes_left == 5 && *in_0.offset(*in_pos as isize) != 0 { + return LZMA_DATA_ERROR; + } + (*rc).code = (*rc).code << 8 | *in_0.offset(*in_pos as isize) as u32; + *in_pos = (*in_pos).wrapping_add(1); + (*rc).init_bytes_left = (*rc).init_bytes_left.wrapping_sub(1); + } + LZMA_STREAM_END +} +#[inline(never)] +fn resume_block_for_sequence(sequence: lzma_decoder_seq) -> u64 { + match sequence { + 0 | 1 => 5979571030476392895, + 2 => 13844743919235296534, + 3 => 18125716024132132232, + 4 => 10535798129821001304, + 5 => 3469750012682708893, + 6 => 1138292997408115650, + 7 => 13912927785247575907, + 8 => 592696588731961849, + 9 => 4174862988780014241, + 10 => 617447976488552541, + 11 => 15418612220330286504, + 12 => 10510472849010538284, + 13 => 7073645523065812117, + 14 => 4420799852307653083, + 16 => 1698084742280242340, + 15 => 5341942013764523046, + 17 => 11808118301119257848, + 18 => 3996983927318648760, + 19 => 12043352250568755004, + 20 => 6834592846991627977, + 21 => 2467942631393454738, + 22 => 17340485688450593529, + _ => 4609795085482299213, + } +} +unsafe extern "C" fn lzma_decode( + coder_ptr: *mut c_void, + dictptr: *mut lzma_dict, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, +) -> lzma_ret { + let mut current_block: u64; + let coder: *mut lzma_lzma1_decoder = coder_ptr as *mut lzma_lzma1_decoder; + let ret: lzma_ret = rc_read_init( + ::core::ptr::addr_of_mut!((*coder).rc), + in_0, + in_pos, + in_size, + ); + if ret != LZMA_STREAM_END { + return ret; + } + let mut dict: lzma_dict = *dictptr; + let dict_start: size_t = dict.pos; + let mut rc: lzma_range_decoder = (*coder).rc; + let mut rc_in_ptr: *const u8 = in_0.offset(*in_pos as isize); + let rc_in_end: *const u8 = in_0.offset(in_size as isize); + let rc_in_fast_end: *const u8 = if rc_in_end.offset_from(rc_in_ptr) <= 20 { + rc_in_ptr + } else { + rc_in_end.offset(-20) + }; + let mut rc_bound: u32 = 0; + let mut state: u32 = (*coder).state as u32; + let mut rep0: u32 = (*coder).rep0; + let mut rep1: u32 = (*coder).rep1; + let mut rep2: u32 = (*coder).rep2; + let mut rep3: u32 = (*coder).rep3; + let pos_mask: u32 = (*coder).pos_mask; + let mut probs: *mut probability = (*coder).probs; + let mut symbol: u32 = (*coder).symbol; + let mut limit: u32 = (*coder).limit; + let mut offset: u32 = (*coder).offset; + let mut len: u32 = (*coder).len; + let literal_mask: u32 = (*coder).literal_mask; + let literal_context_bits: u32 = (*coder).literal_context_bits; + let mut pos_state: u32 = (dict.pos & pos_mask as size_t) as u32; + let mut ret_0: lzma_ret = LZMA_OK; + let mut eopm_is_valid: bool = (*coder).uncompressed_size == LZMA_VLI_UNKNOWN; + let mut might_finish_without_eopm: bool = false; + if (*coder).uncompressed_size != LZMA_VLI_UNKNOWN + && (*coder).uncompressed_size <= dict.limit.wrapping_sub(dict.pos) as lzma_vli + { + dict.limit = dict.pos.wrapping_add((*coder).uncompressed_size as size_t); + might_finish_without_eopm = true; + } + current_block = resume_block_for_sequence((*coder).sequence); + 'c_9380: loop { + match current_block { + 4609795085482299213 => { + (*dictptr).pos = dict.pos; + break; + } + 12043352250568755004 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_REP_LEN_CHOICE; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).rep_len_decoder.choice as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.choice = ((*coder).rep_len_decoder.choice as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub((*coder).rep_len_decoder.choice as u32) + >> RC_MOVE_BITS, + ) as probability; + probs = ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!( + (*coder).rep_len_decoder.low + ) + as *mut [probability; 8]) + .offset(pos_state as isize)) + as *mut probability; + limit = LEN_LOW_SYMBOLS; + len = MATCH_LEN_MIN; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.choice = (*coder).rep_len_decoder.choice + - ((*coder).rep_len_decoder.choice >> RC_MOVE_BITS); + current_block = 6834592846991627977; + continue; + } + current_block = 16690975975023747857; + } + 3996983927318648760 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_IS_REP2; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep2[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep2[state as usize] = ((*coder).is_rep2[state as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).is_rep2[state as usize] as u32) + >> RC_MOVE_BITS, + ) as probability; + let distance_3: u32 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance_3; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep2[state as usize] = (*coder).is_rep2[state as usize] + - ((*coder).is_rep2[state as usize] >> RC_MOVE_BITS); + let distance_4: u32 = rep3; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance_4; + } + current_block = 15498320742470848828; + } + 11808118301119257848 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_IS_REP1; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep1[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep1[state as usize] = ((*coder).is_rep1[state as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).is_rep1[state as usize] as u32) + >> RC_MOVE_BITS, + ) as probability; + let distance_2: u32 = rep1; + rep1 = rep0; + rep0 = distance_2; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep1[state as usize] = (*coder).is_rep1[state as usize] + - ((*coder).is_rep1[state as usize] >> RC_MOVE_BITS); + current_block = 3996983927318648760; + continue; + } + current_block = 15498320742470848828; + } + 5341942013764523046 => { + if dict_put_safe( + ::core::ptr::addr_of_mut!(dict), + dict_get(::core::ptr::addr_of_mut!(dict), rep0), + ) { + (*coder).sequence = SEQ_SHORTREP; + current_block = 4609795085482299213; + continue; + } else { + current_block = 4956146061682418353; + } + } + 1698084742280242340 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_IS_REP0_LONG; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep0_long[state as usize][pos_state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep0_long[state as usize][pos_state as usize] = + ((*coder).is_rep0_long[state as usize][pos_state as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).is_rep0_long[state as usize][pos_state as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability; + state = (if state < LIT_STATES { + STATE_LIT_SHORTREP + } else { + STATE_NONLIT_REP + }) as u32; + current_block = 5341942013764523046; + continue; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep0_long[state as usize][pos_state as usize] = (*coder) + .is_rep0_long[state as usize][pos_state as usize] + - ((*coder).is_rep0_long[state as usize][pos_state as usize] + >> RC_MOVE_BITS); + } + current_block = 15498320742470848828; + } + 4420799852307653083 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_IS_REP0; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep0[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep0[state as usize] = ((*coder).is_rep0[state as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).is_rep0[state as usize] as u32) + >> RC_MOVE_BITS, + ) as probability; + current_block = 1698084742280242340; + continue; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep0[state as usize] = (*coder).is_rep0[state as usize] + - ((*coder).is_rep0[state as usize] >> RC_MOVE_BITS); + current_block = 11808118301119257848; + continue; + } + } + 3469750012682708893 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_IS_REP; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep[state as usize] = ((*coder).is_rep[state as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub((*coder).is_rep[state as usize] as u32) + >> RC_MOVE_BITS, + ) as probability; + state = (if state < LIT_STATES { + STATE_LIT_MATCH + } else { + STATE_NONLIT_MATCH + }) as u32; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + current_block = 1138292997408115650; + continue; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep[state as usize] = (*coder).is_rep[state as usize] + - ((*coder).is_rep[state as usize] >> RC_MOVE_BITS); + if dict_is_distance_valid(::core::ptr::addr_of_mut!(dict), 0) { + current_block = 4420799852307653083; + continue; + } + ret_0 = LZMA_DATA_ERROR; + current_block = 4609795085482299213; + continue; + } + } + 7073645523065812117 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_EOPM; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + ret_0 = if rc.code == 0 { + LZMA_STREAM_END + } else { + LZMA_DATA_ERROR + }; + current_block = 4609795085482299213; + continue; + } + 10510472849010538284 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_ALIGN; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).pos_align[offset.wrapping_add(symbol) as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).pos_align[offset.wrapping_add(symbol) as usize] = + ((*coder).pos_align[offset.wrapping_add(symbol) as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).pos_align[offset.wrapping_add(symbol) as usize] as u32, + ) >> RC_MOVE_BITS, + ) as probability; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).pos_align[offset.wrapping_add(symbol) as usize] = (*coder).pos_align + [offset.wrapping_add(symbol) as usize] + - ((*coder).pos_align[offset.wrapping_add(symbol) as usize] + >> RC_MOVE_BITS); + symbol = symbol.wrapping_add(offset); + } + offset <<= 1; + if offset < ALIGN_SIZE { + current_block = 10510472849010538284; + continue; + } + rep0 = rep0.wrapping_add(symbol); + if rep0 == UINT32_MAX { + current_block = 12043253436139097694; + } else { + current_block = 13383302701878543647; + } + } + 15418612220330286504 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_DIRECT; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc.range >>= 1; + rc.code = rc.code.wrapping_sub(rc.range); + rc_bound = 0u32.wrapping_sub(rc.code >> 31); + rc.code = rc.code.wrapping_add(rc.range & rc_bound); + rep0 = (rep0 << 1).wrapping_add(rc_bound.wrapping_add(1)); + limit -= 1; + if limit > 0 { + current_block = 15418612220330286504; + continue; + } + rep0 <<= ALIGN_BITS; + symbol = 0; + offset = 1; + current_block = 10510472849010538284; + continue; + } + 617447976488552541 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_DIST_MODEL; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = (*probs.offset(symbol as isize) as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + rep0 = (rep0 as u32).wrapping_add(1u32 << offset) as u32; + } + offset += 1; + if offset < limit { + current_block = 617447976488552541; + continue; + } + current_block = 13383302701878543647; + } + 4174862988780014241 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_DIST_SLOT; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = (*probs.offset(symbol as isize) as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if symbol < DIST_SLOTS { + current_block = 4174862988780014241; + continue; + } + symbol = symbol.wrapping_sub(DIST_SLOTS); + if symbol < DIST_MODEL_START { + rep0 = symbol; + } else { + limit = (symbol >> 1).wrapping_sub(1); + rep0 = (2u32).wrapping_add(symbol & 1); + if symbol < DIST_MODEL_END { + rep0 <<= limit; + probs = (::core::ptr::addr_of_mut!((*coder).pos_special) + as *mut probability) + .offset(rep0 as isize) + .offset(-(symbol as isize)) + .offset(-1); + symbol = 1; + offset = 0; + current_block = 617447976488552541; + continue; + } else { + limit = limit.wrapping_sub(ALIGN_BITS); + current_block = 15418612220330286504; + continue; + } + } + current_block = 13383302701878543647; + } + 592696588731961849 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_MATCH_LEN_BITTREE; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = (*probs.offset(symbol as isize) as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if symbol < limit { + current_block = 592696588731961849; + continue; + } + len = len.wrapping_add(symbol.wrapping_sub(limit)); + probs = ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!((*coder).dist_slot) + as *mut [probability; 64]) + .offset( + (if len < (DIST_STATES + MATCH_LEN_MIN) as u32 { + len.wrapping_sub(MATCH_LEN_MIN) + } else { + (DIST_STATES - 1) as u32 + }) as isize, + )) as *mut probability; + symbol = 1; + current_block = 4174862988780014241; + continue; + } + 13912927785247575907 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_MATCH_LEN_CHOICE2; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).match_len_decoder.choice2 as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.choice2 = ((*coder).match_len_decoder.choice2 as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).match_len_decoder.choice2 as u32) + >> RC_MOVE_BITS, + ) as probability; + probs = ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!( + (*coder).match_len_decoder.mid + ) + as *mut [probability; 8]) + .offset(pos_state as isize)) + as *mut probability; + limit = LEN_MID_SYMBOLS; + len = (MATCH_LEN_MIN + LEN_LOW_SYMBOLS) as u32; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.choice2 = (*coder).match_len_decoder.choice2 + - ((*coder).match_len_decoder.choice2 >> RC_MOVE_BITS); + probs = ::core::ptr::addr_of_mut!((*coder).match_len_decoder.high) + as *mut probability; + limit = LEN_HIGH_SYMBOLS; + len = (MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS) as u32; + } + current_block = 8485842003490715114; + } + 1138292997408115650 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_MATCH_LEN_CHOICE; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).match_len_decoder.choice as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.choice = ((*coder).match_len_decoder.choice as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).match_len_decoder.choice as u32) + >> RC_MOVE_BITS, + ) as probability; + probs = ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!( + (*coder).match_len_decoder.low + ) + as *mut [probability; 8]) + .offset(pos_state as isize)) + as *mut probability; + limit = LEN_LOW_SYMBOLS; + len = MATCH_LEN_MIN; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.choice = (*coder).match_len_decoder.choice + - ((*coder).match_len_decoder.choice >> RC_MOVE_BITS); + current_block = 13912927785247575907; + continue; + } + current_block = 8485842003490715114; + } + 10535798129821001304 => { + if dict_put_safe(::core::ptr::addr_of_mut!(dict), symbol as u8) { + (*coder).sequence = SEQ_LITERAL_WRITE; + current_block = 4609795085482299213; + continue; + } else { + current_block = 4956146061682418353; + } + } + 18125716024132132232 => { + let match_bit: u32 = len & offset; + let subcoder_index: u32 = offset.wrapping_add(match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_LITERAL_MATCHED; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(subcoder_index as isize) = + (*probs.offset(subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(subcoder_index as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + offset &= !match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(subcoder_index as isize) -= + *probs.offset(subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + offset &= match_bit; + } + len <<= 1; + if symbol < (1 << 8) as u32 { + current_block = 18125716024132132232; + continue; + } else { + current_block = 10535798129821001304; + continue; + } + } + 5979571030476392895 => { + if might_finish_without_eopm && dict.pos == dict.limit { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_NORMALIZE; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + if rc.code == 0 { + ret_0 = LZMA_STREAM_END; + current_block = 4609795085482299213; + continue; + } else if !(*coder).allow_eopm { + ret_0 = LZMA_DATA_ERROR; + current_block = 4609795085482299213; + continue; + } else { + eopm_is_valid = true; + } + } + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_IS_MATCH; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_match[state as usize][pos_state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_match[state as usize][pos_state as usize] = ((*coder).is_match + [state as usize][pos_state as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).is_match[state as usize][pos_state as usize] as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + probs = (::core::ptr::addr_of_mut!((*coder).literal) as *mut probability) + .offset( + (3_usize).wrapping_mul( + ((dict.pos << 8).wrapping_add( + dict_get0(::core::ptr::addr_of_mut!(dict)) as size_t, + ) & literal_mask as size_t) + << literal_context_bits, + ) as isize, + ); + symbol = 1; + if state < LIT_STATES { + state = if state <= STATE_SHORTREP_LIT_LIT { + STATE_LIT_LIT + } else { + state.wrapping_sub(3) + }; + current_block = 13844743919235296534; + continue; + } else { + state = if state <= STATE_LIT_SHORTREP { + state.wrapping_sub(3) + } else { + state.wrapping_sub(6) + }; + len = (dict_get(::core::ptr::addr_of_mut!(dict), rep0) as u32) << 1; + offset = 0x100; + current_block = 18125716024132132232; + continue; + } + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_match[state as usize][pos_state as usize] = (*coder).is_match + [state as usize][pos_state as usize] + - ((*coder).is_match[state as usize][pos_state as usize] >> RC_MOVE_BITS); + current_block = 3469750012682708893; + continue; + } + } + 13844743919235296534 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_LITERAL; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = (*probs.offset(symbol as isize) as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if symbol < (1 << 8) as u32 { + current_block = 13844743919235296534; + continue; + } else { + current_block = 10535798129821001304; + continue; + } + } + 2467942631393454738 => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_REP_LEN_BITTREE; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = (*probs.offset(symbol as isize) as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if symbol < limit { + current_block = 2467942631393454738; + continue; + } + len = len.wrapping_add(symbol.wrapping_sub(limit)); + current_block = 17340485688450593529; + continue; + } + 17340485688450593529 => { + if dict_repeat( + ::core::ptr::addr_of_mut!(dict), + rep0, + ::core::ptr::addr_of_mut!(len), + ) { + (*coder).sequence = SEQ_COPY; + current_block = 4609795085482299213; + continue; + } else { + current_block = 4956146061682418353; + } + } + _ => { + if rc.range < RC_TOP_VALUE as u32 { + if rc_in_ptr == rc_in_end { + (*coder).sequence = SEQ_REP_LEN_CHOICE2; + current_block = 4609795085482299213; + continue; + } else { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).rep_len_decoder.choice2 as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.choice2 = ((*coder).rep_len_decoder.choice2 as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).rep_len_decoder.choice2 as u32) + >> RC_MOVE_BITS, + ) as probability; + probs = ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!( + (*coder).rep_len_decoder.mid + ) + as *mut [probability; 8]) + .offset(pos_state as isize)) + as *mut probability; + limit = LEN_MID_SYMBOLS; + len = (MATCH_LEN_MIN + LEN_LOW_SYMBOLS) as u32; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.choice2 = (*coder).rep_len_decoder.choice2 + - ((*coder).rep_len_decoder.choice2 >> RC_MOVE_BITS); + probs = ::core::ptr::addr_of_mut!((*coder).rep_len_decoder.high) + as *mut probability; + limit = LEN_HIGH_SYMBOLS; + len = (MATCH_LEN_MIN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS) as u32; + } + current_block = 16690975975023747857; + } + } + match current_block { + 13383302701878543647 => { + if dict_is_distance_valid(::core::ptr::addr_of_mut!(dict), rep0 as size_t) { + current_block = 17340485688450593529; + continue; + } + ret_0 = LZMA_DATA_ERROR; + current_block = 4609795085482299213; + continue; + } + 4956146061682418353 => loop { + pos_state = (dict.pos & pos_mask as size_t) as u32; + if rc_in_ptr >= rc_in_fast_end || dict.pos == dict.limit { + current_block = 5979571030476392895; + continue 'c_9380; + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_match[state as usize][pos_state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_match[state as usize][pos_state as usize] = ((*coder).is_match + [state as usize][pos_state as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).is_match[state as usize][pos_state as usize] as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + probs = (::core::ptr::addr_of_mut!((*coder).literal) as *mut probability) + .offset( + (3_usize).wrapping_mul( + ((dict.pos << 8).wrapping_add( + dict_get0(::core::ptr::addr_of_mut!(dict)) as size_t, + ) & literal_mask as size_t) + << literal_context_bits, + ) as isize, + ); + if state < LIT_STATES { + state = if state <= STATE_SHORTREP_LIT_LIT { + STATE_LIT_LIT + } else { + state.wrapping_sub(3) + }; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + } else { + state = if state <= STATE_LIT_SHORTREP { + state.wrapping_sub(3) + } else { + state.wrapping_sub(6) + }; + let mut t_match_byte: u32 = + dict_get(::core::ptr::addr_of_mut!(dict), rep0) as u32; + let mut t_match_bit: u32 = 0; + let mut t_subcoder_index: u32 = 0; + let mut t_offset: u32 = 0x100; + symbol = 1; + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + t_match_byte <<= 1; + t_match_bit = t_match_byte & t_offset; + t_subcoder_index = t_offset.wrapping_add(t_match_bit).wrapping_add(symbol); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(t_subcoder_index as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(t_subcoder_index as isize) = + (*probs.offset(t_subcoder_index as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(t_subcoder_index as isize) as u32, + ) >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + t_offset &= !t_match_bit; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(t_subcoder_index as isize) -= + *probs.offset(t_subcoder_index as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + t_offset &= t_match_bit; + } + } + dict_put(::core::ptr::addr_of_mut!(dict), symbol as u8); + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_match[state as usize][pos_state as usize] = (*coder).is_match + [state as usize][pos_state as usize] + - ((*coder).is_match[state as usize][pos_state as usize] >> RC_MOVE_BITS); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep[state as usize] = + ((*coder).is_rep[state as usize] as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).is_rep[state as usize] as u32) + >> RC_MOVE_BITS, + ) as probability; + state = (if state < LIT_STATES { + STATE_LIT_MATCH + } else { + STATE_NONLIT_MATCH + }) as u32; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).match_len_decoder.choice as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.choice = + ((*coder).match_len_decoder.choice as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).match_len_decoder.choice as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.low[pos_state as usize][symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] = ((*coder).match_len_decoder.low + [pos_state as usize][symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] = (*coder).match_len_decoder.low + [pos_state as usize][symbol as usize] + - ((*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.low[pos_state as usize][symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] = ((*coder).match_len_decoder.low + [pos_state as usize][symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] = (*coder).match_len_decoder.low + [pos_state as usize][symbol as usize] + - ((*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.low[pos_state as usize][symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] = ((*coder).match_len_decoder.low + [pos_state as usize][symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] = (*coder).match_len_decoder.low + [pos_state as usize][symbol as usize] + - ((*coder).match_len_decoder.low[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + symbol = symbol.wrapping_add((-(1_i32 << 3) + 2) as u32); + len = symbol; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.choice = (*coder).match_len_decoder.choice + - ((*coder).match_len_decoder.choice >> RC_MOVE_BITS); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).match_len_decoder.choice2 as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.choice2 = + ((*coder).match_len_decoder.choice2 as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.choice2 as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] = ((*coder).match_len_decoder.mid + [pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] = (*coder).match_len_decoder.mid + [pos_state as usize] + [symbol as usize] + - ((*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] = ((*coder).match_len_decoder.mid + [pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] = (*coder).match_len_decoder.mid + [pos_state as usize] + [symbol as usize] + - ((*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] = ((*coder).match_len_decoder.mid + [pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] = (*coder).match_len_decoder.mid + [pos_state as usize] + [symbol as usize] + - ((*coder).match_len_decoder.mid[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + symbol = symbol.wrapping_add((-(1_i32 << 3) + 2 + (1 << 3)) as u32); + len = symbol; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.choice2 = + (*coder).match_len_decoder.choice2 + - ((*coder).match_len_decoder.choice2 >> RC_MOVE_BITS); + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).match_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).match_len_decoder.high[symbol as usize] = + ((*coder).match_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).match_len_decoder.high[symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).match_len_decoder.high[symbol as usize] = + (*coder).match_len_decoder.high[symbol as usize] + - ((*coder).match_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + symbol = symbol + .wrapping_add((-(1_i32 << 8) + 2 + (1 << 3) + (1 << 3)) as u32); + len = symbol; + } + } + probs = ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!( + (*coder).dist_slot + ) + as *mut [probability; 64]) + .offset( + (if len < (DIST_STATES + MATCH_LEN_MIN) as u32 { + len.wrapping_sub(MATCH_LEN_MIN) + } else { + (DIST_STATES - 1) as u32 + }) as isize, + )) as *mut probability; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub(*probs.offset(symbol as isize) as u32) + >> RC_MOVE_BITS, + ) as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + } + symbol = symbol.wrapping_add(-(1_i32 << 6) as u32); + if symbol < DIST_MODEL_START { + rep0 = symbol; + } else { + limit = (symbol >> 1).wrapping_sub(1); + rep0 = (2u32).wrapping_add(symbol & 1); + if symbol < DIST_MODEL_END { + rep0 <<= limit; + probs = (::core::ptr::addr_of_mut!((*coder).pos_special) + as *mut probability) + .offset(rep0 as isize) + .offset(-(symbol as isize)) + .offset(-1); + symbol = 1; + offset = 1; + loop { + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul(*probs.offset(symbol as isize) as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + *probs.offset(symbol as isize) = + (*probs.offset(symbol as isize) as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + *probs.offset(symbol as isize) as u32, + ) >> RC_MOVE_BITS, + ) + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + *probs.offset(symbol as isize) -= + *probs.offset(symbol as isize) >> RC_MOVE_BITS; + symbol = (symbol << 1).wrapping_add(1); + rep0 = rep0.wrapping_add(offset); + } + offset <<= 1; + limit -= 1; + if limit == 0 { + break; + } + } + } else { + limit = limit.wrapping_sub(ALIGN_BITS); + loop { + rep0 = (rep0 << 1).wrapping_add(1); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc.range >>= 1; + rc.code = rc.code.wrapping_sub(rc.range); + rc_bound = 0u32.wrapping_sub(rc.code >> 31); + rep0 = rep0.wrapping_add(rc_bound); + rc.code = rc.code.wrapping_add(rc.range & rc_bound); + limit -= 1; + if limit == 0 { + break; + } + } + rep0 <<= ALIGN_BITS; + symbol = 0; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).pos_align[symbol.wrapping_add(1) as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).pos_align[symbol.wrapping_add(1) as usize] = ((*coder) + .pos_align + [symbol.wrapping_add(1) as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).pos_align[symbol.wrapping_add(1) as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).pos_align[symbol.wrapping_add(1) as usize] = + (*coder).pos_align[symbol.wrapping_add(1) as usize] + - ((*coder).pos_align[symbol.wrapping_add(1) as usize] + >> RC_MOVE_BITS); + symbol += 1; + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).pos_align[symbol.wrapping_add(2) as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).pos_align[symbol.wrapping_add(2) as usize] = ((*coder) + .pos_align + [symbol.wrapping_add(2) as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).pos_align[symbol.wrapping_add(2) as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).pos_align[symbol.wrapping_add(2) as usize] = + (*coder).pos_align[symbol.wrapping_add(2) as usize] + - ((*coder).pos_align[symbol.wrapping_add(2) as usize] + >> RC_MOVE_BITS); + symbol = symbol.wrapping_add(2); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).pos_align[symbol.wrapping_add(4) as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).pos_align[symbol.wrapping_add(4) as usize] = ((*coder) + .pos_align + [symbol.wrapping_add(4) as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).pos_align[symbol.wrapping_add(4) as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).pos_align[symbol.wrapping_add(4) as usize] = + (*coder).pos_align[symbol.wrapping_add(4) as usize] + - ((*coder).pos_align[symbol.wrapping_add(4) as usize] + >> RC_MOVE_BITS); + symbol = symbol.wrapping_add(4); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).pos_align[symbol.wrapping_add(8) as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).pos_align[symbol.wrapping_add(8) as usize] = ((*coder) + .pos_align + [symbol.wrapping_add(8) as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).pos_align[symbol.wrapping_add(8) as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).pos_align[symbol.wrapping_add(8) as usize] = + (*coder).pos_align[symbol.wrapping_add(8) as usize] + - ((*coder).pos_align[symbol.wrapping_add(8) as usize] + >> RC_MOVE_BITS); + symbol = symbol.wrapping_add(8); + } + rep0 = rep0.wrapping_add(symbol); + if rep0 == UINT32_MAX { + break; + } + } + } + if !dict_is_distance_valid(::core::ptr::addr_of_mut!(dict), rep0 as size_t) + { + ret_0 = LZMA_DATA_ERROR; + current_block = 4609795085482299213; + continue 'c_9380; + } + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep[state as usize] = (*coder).is_rep[state as usize] + - ((*coder).is_rep[state as usize] >> RC_MOVE_BITS); + if !dict_is_distance_valid(::core::ptr::addr_of_mut!(dict), 0) { + ret_0 = LZMA_DATA_ERROR; + current_block = 4609795085482299213; + continue 'c_9380; + } else { + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep0[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep0[state as usize] = + ((*coder).is_rep0[state as usize] as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).is_rep0[state as usize] as u32) + >> RC_MOVE_BITS, + ) as probability + as probability; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).is_rep0_long[state as usize][pos_state as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep0_long[state as usize][pos_state as usize] = + ((*coder).is_rep0_long[state as usize][pos_state as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).is_rep0_long[state as usize] + [pos_state as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + state = (if state < LIT_STATES { + STATE_LIT_SHORTREP + } else { + STATE_NONLIT_REP + }) as u32; + dict_put( + ::core::ptr::addr_of_mut!(dict), + dict_get(::core::ptr::addr_of_mut!(dict), rep0), + ); + continue; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep0_long[state as usize][pos_state as usize] = + (*coder).is_rep0_long[state as usize][pos_state as usize] + - ((*coder).is_rep0_long[state as usize] + [pos_state as usize] + >> RC_MOVE_BITS); + } + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep0[state as usize] = (*coder).is_rep0[state as usize] + - ((*coder).is_rep0[state as usize] >> RC_MOVE_BITS); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep1[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep1[state as usize] = + ((*coder).is_rep1[state as usize] as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).is_rep1[state as usize] as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + let distance: u32 = rep1; + rep1 = rep0; + rep0 = distance; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep1[state as usize] = (*coder).is_rep1 + [state as usize] + - ((*coder).is_rep1[state as usize] >> RC_MOVE_BITS); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).is_rep2[state as usize] as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).is_rep2[state as usize] = + ((*coder).is_rep2[state as usize] as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).is_rep2[state as usize] as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + let distance_0: u32 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance_0; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).is_rep2[state as usize] = (*coder).is_rep2 + [state as usize] + - ((*coder).is_rep2[state as usize] >> RC_MOVE_BITS); + let distance_1: u32 = rep3; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance_1; + } + } + } + state = (if state < LIT_STATES { + STATE_LIT_LONGREP + } else { + STATE_NONLIT_REP + }) as u32; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).rep_len_decoder.choice as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.choice = + ((*coder).rep_len_decoder.choice as u32).wrapping_add( + RC_BIT_MODEL_TOTAL + .wrapping_sub((*coder).rep_len_decoder.choice as u32) + >> RC_MOVE_BITS, + ) as probability + as probability; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] = + ((*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] = (*coder).rep_len_decoder.low + [pos_state as usize] + [symbol as usize] + - ((*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] = + ((*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] = (*coder).rep_len_decoder.low + [pos_state as usize] + [symbol as usize] + - ((*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] = + ((*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] = (*coder).rep_len_decoder.low + [pos_state as usize] + [symbol as usize] + - ((*coder).rep_len_decoder.low[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + symbol = symbol.wrapping_add((-(1_i32 << 3) + 2) as u32); + len = symbol; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.choice = (*coder).rep_len_decoder.choice + - ((*coder).rep_len_decoder.choice >> RC_MOVE_BITS); + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) + .wrapping_mul((*coder).rep_len_decoder.choice2 as u32); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.choice2 = + ((*coder).rep_len_decoder.choice2 as u32).wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.choice2 as u32, + ) >> RC_MOVE_BITS, + ) as probability + as probability; + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] = ((*coder).rep_len_decoder.mid + [pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] = (*coder).rep_len_decoder.mid + [pos_state as usize] + [symbol as usize] + - ((*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] = ((*coder).rep_len_decoder.mid + [pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] = (*coder).rep_len_decoder.mid + [pos_state as usize] + [symbol as usize] + - ((*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] = ((*coder).rep_len_decoder.mid + [pos_state as usize] + [symbol as usize] + as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] = (*coder).rep_len_decoder.mid + [pos_state as usize] + [symbol as usize] + - ((*coder).rep_len_decoder.mid[pos_state as usize] + [symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + symbol = + symbol.wrapping_add((-(1_i32 << 3) + 2 + (1 << 3)) as u32); + len = symbol; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.choice2 = + (*coder).rep_len_decoder.choice2 + - ((*coder).rep_len_decoder.choice2 >> RC_MOVE_BITS); + symbol = 1; + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + if rc.range < RC_TOP_VALUE as u32 { + rc.range <<= RC_SHIFT_BITS; + rc.code = rc.code << RC_SHIFT_BITS | *rc_in_ptr as u32; + rc_in_ptr = rc_in_ptr.offset(1); + } + rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul( + (*coder).rep_len_decoder.high[symbol as usize] as u32, + ); + if rc.code < rc_bound { + rc.range = rc_bound; + (*coder).rep_len_decoder.high[symbol as usize] = + ((*coder).rep_len_decoder.high[symbol as usize] as u32) + .wrapping_add( + RC_BIT_MODEL_TOTAL.wrapping_sub( + (*coder).rep_len_decoder.high + [symbol as usize] + as u32, + ) >> RC_MOVE_BITS, + ) + as probability + as probability; + symbol <<= 1; + } else { + rc.range = rc.range.wrapping_sub(rc_bound); + rc.code = rc.code.wrapping_sub(rc_bound); + (*coder).rep_len_decoder.high[symbol as usize] = + (*coder).rep_len_decoder.high[symbol as usize] + - ((*coder).rep_len_decoder.high[symbol as usize] + >> RC_MOVE_BITS); + symbol = (symbol << 1).wrapping_add(1); + } + symbol = symbol.wrapping_add( + (-(1_i32 << 8) + 2 + (1 << 3) + (1 << 3)) as u32, + ); + len = symbol; + } + } + } + } + if !dict_repeat( + ::core::ptr::addr_of_mut!(dict), + rep0, + ::core::ptr::addr_of_mut!(len), + ) { + continue; + } + (*coder).sequence = SEQ_COPY; + current_block = 4609795085482299213; + continue 'c_9380; + } + }, + 16690975975023747857 => { + symbol = 1; + current_block = 2467942631393454738; + continue; + } + 15498320742470848828 => { + state = (if state < LIT_STATES { + STATE_LIT_LONGREP + } else { + STATE_NONLIT_REP + }) as u32; + current_block = 12043352250568755004; + continue; + } + 8485842003490715114 => { + symbol = 1; + current_block = 592696588731961849; + continue; + } + _ => {} + } + if eopm_is_valid { + current_block = 7073645523065812117; + continue; + } + ret_0 = LZMA_DATA_ERROR; + current_block = 4609795085482299213; + } + (*dictptr).full = dict.full; + (*coder).rc = rc; + *in_pos = rc_in_ptr.offset_from(in_0) as size_t; + (*coder).state = state as lzma_lzma_state; + (*coder).rep0 = rep0; + (*coder).rep1 = rep1; + (*coder).rep2 = rep2; + (*coder).rep3 = rep3; + (*coder).probs = probs; + (*coder).symbol = symbol; + (*coder).limit = limit; + (*coder).offset = offset; + (*coder).len = len; + if (*coder).uncompressed_size != LZMA_VLI_UNKNOWN { + (*coder).uncompressed_size = (*coder) + .uncompressed_size + .wrapping_sub(dict.pos.wrapping_sub(dict_start) as lzma_vli); + if (*coder).uncompressed_size == 0 + && ret_0 == LZMA_OK + && ((*coder).sequence == SEQ_LITERAL_WRITE + || (*coder).sequence == SEQ_SHORTREP + || (*coder).sequence == SEQ_COPY) + { + ret_0 = LZMA_DATA_ERROR; + } + } + if ret_0 == LZMA_STREAM_END { + (*coder).rc.range = UINT32_MAX; + (*coder).rc.code = 0; + (*coder).rc.init_bytes_left = 5; + (*coder).sequence = SEQ_IS_MATCH; + } + ret_0 +} +unsafe extern "C" fn lzma_decoder_uncompressed( + coder_ptr: *mut c_void, + uncompressed_size: lzma_vli, + allow_eopm: bool, +) { + let coder: *mut lzma_lzma1_decoder = coder_ptr as *mut lzma_lzma1_decoder; + (*coder).uncompressed_size = uncompressed_size; + (*coder).allow_eopm = allow_eopm; +} +unsafe extern "C" fn lzma_decoder_reset(coder_ptr: *mut c_void, opt: *const c_void) { + let coder: *mut lzma_lzma1_decoder = coder_ptr as *mut lzma_lzma1_decoder; + let options: *const lzma_options_lzma = opt as *const lzma_options_lzma; + (*coder).pos_mask = (1u32 << (*options).pb).wrapping_sub(1) as u32; + literal_init( + ::core::ptr::addr_of_mut!((*coder).literal) as *mut probability, + (*options).lc, + (*options).lp, + ); + (*coder).literal_context_bits = (*options).lc; + (*coder).literal_mask = (0x100u32 << (*options).lp).wrapping_sub(0x100 >> (*options).lc); + (*coder).state = STATE_LIT_LIT; + (*coder).rep0 = 0; + (*coder).rep1 = 0; + (*coder).rep2 = 0; + (*coder).rep3 = 0; + (*coder).pos_mask = (1u32 << (*options).pb).wrapping_sub(1) as u32; + (*coder).rc.range = UINT32_MAX; + (*coder).rc.code = 0; + (*coder).rc.init_bytes_left = 5; + let mut i: u32 = 0; + while i < STATES { + let mut j: u32 = 0; + while j <= (*coder).pos_mask { + (*coder).is_match[i as usize][j as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep0_long[i as usize][j as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + j += 1; + } + (*coder).is_rep[i as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep0[i as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep1[i as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep2[i as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + i += 1; + } + let mut i_0: u32 = 0; + while i_0 < DIST_STATES { + let mut bt_i: u32 = 0; + while bt_i < (1 << 6) as u32 { + (*coder).dist_slot[i_0 as usize][bt_i as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i += 1; + } + i_0 += 1; + } + let mut i_1: u32 = 0; + while i_1 < (FULL_DISTANCES - DIST_MODEL_END) as u32 { + (*coder).pos_special[i_1 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + i_1 += 1; + } + let mut bt_i_0: u32 = 0; + while bt_i_0 < (1 << 4) as u32 { + (*coder).pos_align[bt_i_0 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_0 += 1; + } + let num_pos_states: u32 = 1 << (*options).pb; + (*coder).match_len_decoder.choice = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).match_len_decoder.choice2 = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).rep_len_decoder.choice = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).rep_len_decoder.choice2 = (RC_BIT_MODEL_TOTAL >> 1) as probability; + let mut pos_state: u32 = 0; + while pos_state < num_pos_states { + let mut bt_i_1: u32 = 0; + while bt_i_1 < (1 << 3) as u32 { + (*coder).match_len_decoder.low[pos_state as usize][bt_i_1 as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_1 += 1; + } + let mut bt_i_2: u32 = 0; + while bt_i_2 < (1 << 3) as u32 { + (*coder).match_len_decoder.mid[pos_state as usize][bt_i_2 as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_2 += 1; + } + let mut bt_i_3: u32 = 0; + while bt_i_3 < (1 << 3) as u32 { + (*coder).rep_len_decoder.low[pos_state as usize][bt_i_3 as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_3 += 1; + } + let mut bt_i_4: u32 = 0; + while bt_i_4 < (1 << 3) as u32 { + (*coder).rep_len_decoder.mid[pos_state as usize][bt_i_4 as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_4 += 1; + } + pos_state += 1; + } + let mut bt_i_5: u32 = 0; + while bt_i_5 < (1 << 8) as u32 { + (*coder).match_len_decoder.high[bt_i_5 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_5 += 1; + } + let mut bt_i_6: u32 = 0; + while bt_i_6 < (1 << 8) as u32 { + (*coder).rep_len_decoder.high[bt_i_6 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_6 += 1; + } + (*coder).sequence = SEQ_IS_MATCH; + (*coder).probs = core::ptr::null_mut(); + (*coder).symbol = 0; + (*coder).limit = 0; + (*coder).offset = 0; + (*coder).len = 0; +} +pub unsafe fn lzma_lzma_decoder_create( + lz: *mut lzma_lz_decoder, + allocator: *const lzma_allocator, + options: *const lzma_options_lzma, + lz_options: *mut lzma_lz_options, +) -> lzma_ret { + if (*lz).coder.is_null() { + (*lz).coder = + crate::alloc::internal_alloc_object::(allocator) as *mut c_void; + if (*lz).coder.is_null() { + return LZMA_MEM_ERROR; + } + (*lz).code = Some( + lzma_decode + as unsafe extern "C" fn( + *mut c_void, + *mut lzma_dict, + *const u8, + *mut size_t, + size_t, + ) -> lzma_ret, + ); + (*lz).reset = + Some(lzma_decoder_reset as unsafe extern "C" fn(*mut c_void, *const c_void) -> ()); + (*lz).set_uncompressed = Some( + lzma_decoder_uncompressed as unsafe extern "C" fn(*mut c_void, lzma_vli, bool) -> (), + ); + } + (*lz_options).dict_size = (*options).dict_size as size_t; + (*lz_options).preset_dict = (*options).preset_dict; + (*lz_options).preset_dict_size = (*options).preset_dict_size as size_t; + LZMA_OK +} +unsafe extern "C" fn lzma_decoder_init( + lz: *mut lzma_lz_decoder, + allocator: *const lzma_allocator, + id: lzma_vli, + options: *const c_void, + lz_options: *mut lzma_lz_options, +) -> lzma_ret { + if !is_lclppb_valid(options as *const lzma_options_lzma) { + return LZMA_PROG_ERROR; + } + let mut uncomp_size: lzma_vli = LZMA_VLI_UNKNOWN; + let mut allow_eopm: bool = true; + if id == LZMA_FILTER_LZMA1EXT { + let opt: *const lzma_options_lzma = options as *const lzma_options_lzma; + if (*opt).ext_flags & !(LZMA_LZMA1EXT_ALLOW_EOPM as u32) != 0 { + return LZMA_OPTIONS_ERROR; + } + uncomp_size = ((*opt).ext_size_low as u64).wrapping_add(((*opt).ext_size_high as u64) << 32) + as lzma_vli; + allow_eopm = (*opt).ext_flags & LZMA_LZMA1EXT_ALLOW_EOPM as u32 != 0 + || uncomp_size == LZMA_VLI_UNKNOWN; + } + let ret_: lzma_ret = lzma_lzma_decoder_create( + lz, + allocator, + options as *const lzma_options_lzma, + lz_options, + ); + if ret_ != LZMA_OK { + return ret_; + } + lzma_decoder_reset((*lz).coder, options); + lzma_decoder_uncompressed((*lz).coder, uncomp_size, allow_eopm); + LZMA_OK +} +pub unsafe extern "C" fn lzma_lzma_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + lzma_lz_decoder_init( + next, + allocator, + filters, + Some( + lzma_decoder_init + as unsafe extern "C" fn( + *mut lzma_lz_decoder, + *const lzma_allocator, + lzma_vli, + *const c_void, + *mut lzma_lz_options, + ) -> lzma_ret, + ), + ) +} +pub unsafe fn lzma_lzma_lclppb_decode(options: *mut lzma_options_lzma, mut byte: u8) -> bool { + if byte > (4 * 5 + 4) * 9 + 8 { + return true; + } + (*options).pb = (byte / (9 * 5)) as u32; + byte = (byte as u32).wrapping_sub((*options).pb.wrapping_mul(9u32).wrapping_mul(5)) as u8; + (*options).lp = (byte / 9) as u32; + (*options).lc = (byte as u32).wrapping_sub((*options).lp.wrapping_mul(9)); + (*options).lc.wrapping_add((*options).lp) > LZMA_LCLP_MAX +} +pub extern "C" fn lzma_lzma_decoder_memusage_nocheck(options: *const c_void) -> u64 { + return unsafe { + let opt: *const lzma_options_lzma = options as *const lzma_options_lzma; + (core::mem::size_of::() as u64) + .wrapping_add(lzma_lz_decoder_memusage((*opt).dict_size as size_t)) + }; +} +pub extern "C" fn lzma_lzma_decoder_memusage(options: *const c_void) -> u64 { + if !unsafe { is_lclppb_valid(options as *const lzma_options_lzma) } { + return UINT64_MAX; + } + lzma_lzma_decoder_memusage_nocheck(options) +} +pub unsafe extern "C" fn lzma_lzma_props_decode( + options: *mut *mut c_void, + allocator: *const lzma_allocator, + props: *const u8, + props_size: size_t, +) -> lzma_ret { + if props_size != 5 { + return LZMA_OPTIONS_ERROR; + } + let opt: *mut lzma_options_lzma = + lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_options_lzma; + if opt.is_null() { + return LZMA_MEM_ERROR; + } + if lzma_lzma_lclppb_decode(opt, *props) { + lzma_free(opt as *mut c_void, allocator); + return LZMA_OPTIONS_ERROR; + } else { + (*opt).dict_size = read32le(props.offset(1)); + (*opt).preset_dict = core::ptr::null(); + (*opt).preset_dict_size = 0; + *options = opt as *mut c_void; + return LZMA_OK; + }; +} diff --git a/liblzma-rs/src/lzma/lzma_encoder.rs b/liblzma-rs/src/lzma/lzma_encoder.rs new file mode 100644 index 00000000..43588b40 --- /dev/null +++ b/liblzma-rs/src/lzma/lzma_encoder.rs @@ -0,0 +1,1084 @@ +use crate::lz::lz_encoder::{lzma_lz_encoder_init, lzma_lz_encoder_memusage, lzma_lz_options}; +use crate::lzma::lzma_encoder_optimum_fast::lzma_lzma_optimum_fast; +use crate::lzma::lzma_encoder_optimum_normal::lzma_lzma_optimum_normal; +use crate::types::*; +#[inline] +unsafe fn rc_reset(rc: *mut lzma_range_encoder) { + (*rc).low = 0; + (*rc).cache_size = 1; + (*rc).range = UINT32_MAX; + (*rc).cache = 0; + (*rc).out_total = 0; + (*rc).count = 0; + (*rc).pos = 0; +} +#[inline] +unsafe fn rc_forget(rc: *mut lzma_range_encoder) { + (*rc).count = 0; +} +#[inline] +unsafe fn rc_bit(rc: *mut lzma_range_encoder, prob: *mut probability, bit: u32) { + *rc_symbol_slot_mut(rc, (*rc).count) = bit as rc_symbol; + *rc_prob_slot_mut(rc, (*rc).count) = prob; + (*rc).count += 1; +} + +#[inline(always)] +unsafe fn rc_symbol_slot_mut(rc: *mut lzma_range_encoder, index: size_t) -> *mut rc_symbol { + debug_assert!(index < 53); + (::core::ptr::addr_of_mut!((*rc).symbols) as *mut rc_symbol).add(index) +} + +#[inline(always)] +unsafe fn rc_prob_slot_mut(rc: *mut lzma_range_encoder, index: size_t) -> *mut *mut probability { + debug_assert!(index < 53); + (::core::ptr::addr_of_mut!((*rc).probs) as *mut *mut probability).add(index) +} + +#[inline(always)] +unsafe fn coder_rep_slot_mut(coder: *mut lzma_lzma1_encoder, index: usize) -> *mut u32 { + debug_assert!(index < REPS as usize); + (::core::ptr::addr_of_mut!((*coder).reps) as *mut u32).add(index) +} +#[inline] +unsafe fn rc_bittree( + rc: *mut lzma_range_encoder, + probs: *mut probability, + mut bit_count: u32, + symbol: u32, +) { + let mut model_index: u32 = 1; + loop { + bit_count -= 1; + let bit: u32 = symbol >> bit_count & 1; + rc_bit( + rc, + probs.offset(model_index as isize) as *mut probability, + bit, + ); + model_index = (model_index << 1) + bit; + if bit_count == 0 { + break; + } + } +} +#[inline] +unsafe fn rc_bittree_reverse( + rc: *mut lzma_range_encoder, + probs: *mut probability, + mut bit_count: u32, + mut symbol: u32, +) { + let mut model_index: u32 = 1; + loop { + let bit: u32 = symbol & 1; + symbol >>= 1; + rc_bit( + rc, + probs.offset(model_index as isize) as *mut probability, + bit, + ); + model_index = (model_index << 1) + bit; + bit_count -= 1; + if bit_count == 0 { + break; + } + } +} +#[inline] +unsafe fn rc_direct(rc: *mut lzma_range_encoder, value: u32, mut bit_count: u32) { + loop { + bit_count -= 1; + *rc_symbol_slot_mut(rc, (*rc).count) = + ((RC_DIRECT_0 as u32) + (value >> bit_count & 1)) as rc_symbol; + (*rc).count += 1; + if bit_count == 0 { + break; + } + } +} +#[inline] +unsafe fn rc_flush(rc: *mut lzma_range_encoder) { + let mut i: size_t = 0; + while i < 5 { + *rc_symbol_slot_mut(rc, (*rc).count) = RC_FLUSH; + (*rc).count += 1; + i += 1; + } +} +#[inline] +unsafe fn rc_shift_low( + rc: *mut lzma_range_encoder, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> bool { + if ((*rc).low as u32) < 0xff000000 || ((*rc).low >> 32) as u32 != 0 { + loop { + if *out_pos == out_size { + return true; + } + *out.offset(*out_pos as isize) = (*rc).cache.wrapping_add(((*rc).low >> 32) as u8); + *out_pos += 1; + (*rc).out_total += 1; + (*rc).cache = 0xff; + (*rc).cache_size -= 1; + if (*rc).cache_size == 0 { + break; + } + } + (*rc).cache = ((*rc).low >> 24 & 0xff as u64) as u8; + } + (*rc).cache_size += 1; + (*rc).low = ((*rc).low & 0xffffff as u64) << RC_SHIFT_BITS; + false +} +#[inline] +unsafe fn rc_shift_low_dummy( + low: *mut u64, + cache_size: *mut u64, + cache: *mut u8, + out_pos: *mut u64, + out_size: u64, +) -> bool { + if (*low as u32) < 0xff000000 || (*low >> 32) as u32 != 0 { + loop { + if *out_pos == out_size { + return true; + } + *out_pos += 1; + *cache = 0xff; + *cache_size -= 1; + if *cache_size == 0 { + break; + } + } + *cache = (*low >> 24 & 0xff as u64) as u8; + } + *cache_size += 1; + *low = (*low & 0xffffff as u64) << RC_SHIFT_BITS; + false +} +#[inline] +unsafe fn rc_encode( + rc: *mut lzma_range_encoder, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> bool { + while (*rc).pos < (*rc).count { + if (*rc).range < RC_TOP_VALUE as u32 { + if rc_shift_low(rc, out, out_pos, out_size) { + return true; + } + (*rc).range <<= RC_SHIFT_BITS; + } + match *rc_symbol_slot_mut(rc, (*rc).pos) { + 0 => { + let mut prob: probability = **rc_prob_slot_mut(rc, (*rc).pos); + (*rc).range = ((*rc).range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul(prob as u32); + prob = (prob as u32) + .wrapping_add(RC_BIT_MODEL_TOTAL.wrapping_sub(prob as u32) >> RC_MOVE_BITS) + as probability; + **rc_prob_slot_mut(rc, (*rc).pos) = prob; + } + 1 => { + let mut prob_0: probability = **rc_prob_slot_mut(rc, (*rc).pos); + let bound: u32 = + (prob_0 as u32).wrapping_mul((*rc).range >> RC_BIT_MODEL_TOTAL_BITS); + (*rc).low = (*rc).low.wrapping_add(bound as u64); + (*rc).range = (*rc).range.wrapping_sub(bound); + prob_0 -= prob_0 >> RC_MOVE_BITS; + **rc_prob_slot_mut(rc, (*rc).pos) = prob_0; + } + 2 => { + (*rc).range >>= 1; + } + 3 => { + (*rc).range >>= 1; + (*rc).low = (*rc).low.wrapping_add((*rc).range as u64); + } + 4 => { + (*rc).range = UINT32_MAX; + loop { + if rc_shift_low(rc, out, out_pos, out_size) { + return true; + } + (*rc).pos += 1; + if (*rc).pos >= (*rc).count { + break; + } + } + rc_reset(rc); + return false; + } + _ => {} + } + (*rc).pos += 1; + } + (*rc).count = 0; + (*rc).pos = 0; + false +} +#[inline] +unsafe fn rc_encode_dummy(rc: *const lzma_range_encoder, out_limit: u64) -> bool { + let mut low: u64 = (*rc).low; + let mut cache_size: u64 = (*rc).cache_size; + let mut range: u32 = (*rc).range; + let mut cache: u8 = (*rc).cache; + let mut out_pos: u64 = (*rc).out_total; + let mut pos: size_t = (*rc).pos; + loop { + if range < RC_TOP_VALUE as u32 { + if rc_shift_low_dummy( + ::core::ptr::addr_of_mut!(low), + ::core::ptr::addr_of_mut!(cache_size), + ::core::ptr::addr_of_mut!(cache), + ::core::ptr::addr_of_mut!(out_pos), + out_limit, + ) { + return true; + } + range <<= RC_SHIFT_BITS; + } + if pos == (*rc).count { + break; + } + match (*rc).symbols[pos as usize] { + 0 => { + let prob: probability = *(*rc).probs[pos as usize]; + range = (range >> RC_BIT_MODEL_TOTAL_BITS).wrapping_mul(prob as u32); + } + 1 => { + let prob_0: probability = *(*rc).probs[pos as usize]; + let bound: u32 = (prob_0 as u32).wrapping_mul(range >> RC_BIT_MODEL_TOTAL_BITS); + low = low.wrapping_add(bound as u64); + range = range.wrapping_sub(bound); + } + 2 => { + range >>= 1; + } + 3 => { + range >>= 1; + low = low.wrapping_add(range as u64); + } + 4 | _ => {} + } + pos += 1; + } + pos = 0; + while pos < 5 { + if rc_shift_low_dummy( + ::core::ptr::addr_of_mut!(low), + ::core::ptr::addr_of_mut!(cache_size), + ::core::ptr::addr_of_mut!(cache), + ::core::ptr::addr_of_mut!(out_pos), + out_limit, + ) { + return true; + } + pos += 1; + } + false +} +#[inline] +unsafe fn rc_pending(rc: *const lzma_range_encoder) -> u64 { + (*rc).cache_size + 5 - 1 +} +pub const LEN_SYMBOLS: u32 = LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS; +pub const MATCH_LEN_MAX: u32 = MATCH_LEN_MIN + LEN_SYMBOLS - 1; +#[inline] +unsafe fn literal_matched( + rc: *mut lzma_range_encoder, + subcoder: *mut probability, + mut match_byte: u32, + mut symbol: u32, +) { + let mut offset: u32 = 0x100; + symbol = (symbol as u32 + (1u32 << 8)) as u32; + loop { + match_byte <<= 1; + let match_bit: u32 = match_byte & offset; + let subcoder_index: u32 = offset + match_bit + (symbol >> 8); + let bit: u32 = symbol >> 7 & 1; + rc_bit( + rc, + subcoder.offset(subcoder_index as isize) as *mut probability, + bit, + ); + symbol <<= 1; + offset &= !(match_byte ^ symbol); + if symbol >= 1 << 16 { + break; + } + } +} +#[inline] +unsafe fn literal(coder: *mut lzma_lzma1_encoder, mf: *mut lzma_mf, position: u32) { + let cur_byte: u8 = *(*mf) + .buffer + .offset(((*mf).read_pos - (*mf).read_ahead) as isize); + let subcoder: *mut probability = + (::core::ptr::addr_of_mut!((*coder).literal) as *mut probability).offset( + (3u32 + * (((position << 8) + + *(*mf) + .buffer + .offset(((*mf).read_pos - (*mf).read_ahead - 1) as isize) + as u32) + & (*coder).literal_mask) + << (*coder).literal_context_bits) as isize, + ); + if ((*coder).state as u32) < LIT_STATES { + (*coder).state = (if (*coder).state <= STATE_SHORTREP_LIT_LIT { + STATE_LIT_LIT + } else { + (*coder).state as u32 - 3 + }) as lzma_lzma_state; + rc_bittree( + ::core::ptr::addr_of_mut!((*coder).rc), + subcoder, + 8, + cur_byte as u32, + ); + } else { + (*coder).state = (if (*coder).state <= STATE_LIT_SHORTREP { + (*coder).state as u32 - 3 + } else { + (*coder).state as u32 - 6 + }) as lzma_lzma_state; + let match_byte: u8 = *(*mf).buffer.offset( + ((*mf).read_pos - *coder_rep_slot_mut(coder, 0) - 1 - (*mf).read_ahead) as isize, + ); + literal_matched( + ::core::ptr::addr_of_mut!((*coder).rc), + subcoder, + match_byte as u32, + cur_byte as u32, + ); + }; +} +#[inline(always)] +unsafe fn length_prices_row(lc: *mut lzma_length_encoder, pos_state: u32) -> *mut u32 { + ::core::ptr::addr_of_mut!( + *(::core::ptr::addr_of_mut!((*lc).prices) as *mut [u32; 272]).add(pos_state as usize) + ) as *mut u32 +} +#[inline(always)] +unsafe fn length_low_probs(lc: *mut lzma_length_encoder, pos_state: u32) -> *mut probability { + ::core::ptr::addr_of_mut!( + *(::core::ptr::addr_of_mut!((*lc).low) as *mut [probability; 8]).add(pos_state as usize) + ) as *mut probability +} +#[inline(always)] +unsafe fn length_mid_probs(lc: *mut lzma_length_encoder, pos_state: u32) -> *mut probability { + ::core::ptr::addr_of_mut!( + *(::core::ptr::addr_of_mut!((*lc).mid) as *mut [probability; 8]).add(pos_state as usize) + ) as *mut probability +} +#[inline(always)] +unsafe fn length_counter(lc: *mut lzma_length_encoder, pos_state: u32) -> *mut u32 { + debug_assert!((pos_state as usize) < (*lc).counters.len()); + (::core::ptr::addr_of_mut!((*lc).counters) as *mut u32).add(pos_state as usize) +} +#[inline(always)] +unsafe fn is_match_prob(coder: *mut lzma_lzma1_encoder, pos_state: u32) -> *mut probability { + (::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!((*coder).is_match) + as *mut [probability; 16]) + .add((*coder).state as usize)) as *mut probability) + .add(pos_state as usize) +} +#[inline(always)] +unsafe fn is_rep_prob(coder: *mut lzma_lzma1_encoder) -> *mut probability { + (::core::ptr::addr_of_mut!((*coder).is_rep) as *mut probability).add((*coder).state as usize) +} +unsafe fn length_update_prices(lc: *mut lzma_length_encoder, pos_state: u32) { + let table_size: u32 = (*lc).table_size; + *length_counter(lc, pos_state) = table_size; + let a0: u32 = rc_bit_0_price((*lc).choice) as u32; + let a1: u32 = rc_bit_1_price((*lc).choice) as u32; + let b0: u32 = a1 + rc_bit_0_price((*lc).choice2) as u32; + let b1: u32 = a1 + rc_bit_1_price((*lc).choice2) as u32; + let prices: *mut u32 = length_prices_row(lc, pos_state); + let low: *mut probability = length_low_probs(lc, pos_state); + let mid: *mut probability = length_mid_probs(lc, pos_state); + let high: *mut probability = ::core::ptr::addr_of_mut!((*lc).high) as *mut probability; + let mut i: u32 = 0; + while i < table_size && i < LEN_LOW_SYMBOLS { + *prices.add(i as usize) = a0 + rc_bittree_price(low, LEN_LOW_BITS, i); + i += 1; + } + while i < table_size && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS { + *prices.add(i as usize) = b0 + rc_bittree_price(mid, LEN_MID_BITS, i - LEN_LOW_SYMBOLS); + i += 1; + } + while i < table_size { + *prices.add(i as usize) = + b1 + rc_bittree_price(high, LEN_HIGH_BITS, i - LEN_LOW_SYMBOLS - LEN_MID_SYMBOLS); + i += 1; + } +} +#[inline] +unsafe fn length( + rc: *mut lzma_range_encoder, + lc: *mut lzma_length_encoder, + pos_state: u32, + mut len: u32, + fast_mode: bool, +) { + len -= MATCH_LEN_MIN; + if len < LEN_LOW_SYMBOLS { + rc_bit(rc, ::core::ptr::addr_of_mut!((*lc).choice), 0); + rc_bittree(rc, length_low_probs(lc, pos_state), LEN_LOW_BITS, len); + } else { + rc_bit(rc, ::core::ptr::addr_of_mut!((*lc).choice), 1); + len -= LEN_LOW_SYMBOLS; + if len < LEN_MID_SYMBOLS { + rc_bit(rc, ::core::ptr::addr_of_mut!((*lc).choice2), 0); + rc_bittree(rc, length_mid_probs(lc, pos_state), LEN_MID_BITS, len); + } else { + rc_bit(rc, ::core::ptr::addr_of_mut!((*lc).choice2), 1); + len -= LEN_MID_SYMBOLS; + rc_bittree( + rc, + ::core::ptr::addr_of_mut!((*lc).high) as *mut probability, + LEN_HIGH_BITS, + len, + ); + } + } + if !fast_mode { + (*lc).counters[pos_state as usize] -= 1; + if (*lc).counters[pos_state as usize] == 0 { + length_update_prices(lc, pos_state); + } + } +} +#[inline] +unsafe fn match_0(coder: *mut lzma_lzma1_encoder, pos_state: u32, distance: u32, len: u32) { + (*coder).state = (if ((*coder).state as u32) < LIT_STATES { + STATE_LIT_MATCH + } else { + STATE_NONLIT_MATCH + }) as lzma_lzma_state; + length( + ::core::ptr::addr_of_mut!((*coder).rc), + ::core::ptr::addr_of_mut!((*coder).match_len_encoder), + pos_state, + len, + (*coder).fast_mode, + ); + let dist_slot: u32 = get_dist_slot(distance) as u32; + let dist_state: u32 = if len < (DIST_STATES + MATCH_LEN_MIN) as u32 { + len - MATCH_LEN_MIN + } else { + (DIST_STATES - 1) as u32 + }; + rc_bittree( + ::core::ptr::addr_of_mut!((*coder).rc), + ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!((*coder).dist_slot) + as *mut [probability; 64]) + .offset(dist_state as isize)) as *mut probability, + DIST_SLOT_BITS, + dist_slot, + ); + if dist_slot >= DIST_MODEL_START { + let footer_bits: u32 = (dist_slot >> 1) - 1; + let base: u32 = (2 | dist_slot & 1) << footer_bits; + let dist_reduced: u32 = distance - base; + if dist_slot < DIST_MODEL_END { + rc_bittree_reverse( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!((*coder).dist_special) as *mut probability) + .offset(base as isize) + .offset(-(dist_slot as isize)) + .offset(-1), + footer_bits, + dist_reduced, + ); + } else { + rc_direct( + ::core::ptr::addr_of_mut!((*coder).rc), + dist_reduced >> ALIGN_BITS, + footer_bits - ALIGN_BITS, + ); + rc_bittree_reverse( + ::core::ptr::addr_of_mut!((*coder).rc), + ::core::ptr::addr_of_mut!((*coder).dist_align) as *mut probability, + ALIGN_BITS, + dist_reduced & ALIGN_MASK, + ); + (*coder).align_price_count += 1; + } + } + *coder_rep_slot_mut(coder, 3) = *coder_rep_slot_mut(coder, 2); + *coder_rep_slot_mut(coder, 2) = *coder_rep_slot_mut(coder, 1); + *coder_rep_slot_mut(coder, 1) = *coder_rep_slot_mut(coder, 0); + *coder_rep_slot_mut(coder, 0) = distance; + (*coder).match_price_count += 1; +} +#[inline] +unsafe fn rep_match(coder: *mut lzma_lzma1_encoder, pos_state: u32, rep: u32, len: u32) { + if rep == 0 { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!((*coder).is_rep0) as *mut probability) + .offset((*coder).state as isize) as *mut probability, + 0, + ); + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!((*coder).is_rep0_long) + as *mut [probability; 16]) + .offset((*coder).state as isize)) as *mut probability) + .offset(pos_state as isize) as *mut probability, + (len != 1) as u32, + ); + } else { + let distance: u32 = *coder_rep_slot_mut(coder, rep as usize); + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!((*coder).is_rep0) as *mut probability) + .offset((*coder).state as isize) as *mut probability, + 1, + ); + if rep == 1 { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!((*coder).is_rep1) as *mut probability) + .offset((*coder).state as isize) as *mut probability, + 0, + ); + } else { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!((*coder).is_rep1) as *mut probability) + .offset((*coder).state as isize) as *mut probability, + 1, + ); + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + (::core::ptr::addr_of_mut!((*coder).is_rep2) as *mut probability) + .offset((*coder).state as isize) as *mut probability, + rep - 2, + ); + if rep == 3 { + *coder_rep_slot_mut(coder, 3) = *coder_rep_slot_mut(coder, 2); + } + *coder_rep_slot_mut(coder, 2) = *coder_rep_slot_mut(coder, 1); + } + *coder_rep_slot_mut(coder, 1) = *coder_rep_slot_mut(coder, 0); + *coder_rep_slot_mut(coder, 0) = distance; + } + if len == 1 { + (*coder).state = (if ((*coder).state as u32) < LIT_STATES { + STATE_LIT_SHORTREP + } else { + STATE_NONLIT_REP + }) as lzma_lzma_state; + } else { + length( + ::core::ptr::addr_of_mut!((*coder).rc), + ::core::ptr::addr_of_mut!((*coder).rep_len_encoder), + pos_state, + len, + (*coder).fast_mode, + ); + (*coder).state = (if ((*coder).state as u32) < LIT_STATES { + STATE_LIT_LONGREP + } else { + STATE_NONLIT_REP + }) as lzma_lzma_state; + }; +} +unsafe fn encode_symbol( + coder: *mut lzma_lzma1_encoder, + mf: *mut lzma_mf, + back: u32, + len: u32, + position: u32, +) { + let pos_state: u32 = position & (*coder).pos_mask; + if back == UINT32_MAX { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_match_prob(coder, pos_state), + 0, + ); + literal(coder, mf, position); + } else { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_match_prob(coder, pos_state), + 1, + ); + if back < REPS { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_rep_prob(coder), + 1, + ); + rep_match(coder, pos_state, back, len); + } else { + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_rep_prob(coder), + 0, + ); + match_0(coder, pos_state, back - REPS, len); + } + } + (*mf).read_ahead -= len; +} +unsafe fn encode_init(coder: *mut lzma_lzma1_encoder, mf: *mut lzma_mf) -> bool { + if (*mf).read_pos == (*mf).read_limit { + if (*mf).action == LZMA_RUN { + return false; + } + } else { + mf_skip(mf, 1); + (*mf).read_ahead = 0; + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_match_prob(coder, 0), + 0, + ); + rc_bittree( + ::core::ptr::addr_of_mut!((*coder).rc), + ::core::ptr::addr_of_mut!((*coder).literal) as *mut probability, + 8, + *(*mf).buffer as u32, + ); + (*coder).uncomp_size += 1; + } + (*coder).is_initialized = true; + true +} +unsafe fn encode_eopm(coder: *mut lzma_lzma1_encoder, position: u32) { + let pos_state: u32 = position & (*coder).pos_mask; + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_match_prob(coder, pos_state), + 1, + ); + rc_bit( + ::core::ptr::addr_of_mut!((*coder).rc), + is_rep_prob(coder), + 0, + ); + match_0(coder, pos_state, UINT32_MAX, MATCH_LEN_MIN); +} +pub const LOOP_INPUT_MAX: u32 = OPTS + 1; +#[cold] +#[inline(never)] +unsafe fn finish_lzma_stream( + coder: *mut lzma_lzma1_encoder, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + let rc = ::core::ptr::addr_of_mut!((*coder).rc); + if !(*coder).uncomp_size_ptr.is_null() { + *(*coder).uncomp_size_ptr = (*coder).uncomp_size; + } + if (*coder).use_eopm { + encode_eopm(coder, (*coder).uncomp_size as u32); + } + rc_flush(rc); + if rc_encode(rc, out, out_pos, out_size) { + (*coder).is_flushed = true; + return LZMA_OK; + } + LZMA_STREAM_END +} +#[cold] +#[inline(never)] +unsafe fn out_limit_reached(coder: *mut lzma_lzma1_encoder) -> bool { + let rc = ::core::ptr::addr_of_mut!((*coder).rc); + if (*coder).out_limit == 0 || !rc_encode_dummy(rc, (*coder).out_limit) { + return false; + } + rc_forget(rc); + true +} +pub unsafe fn lzma_lzma_encode( + coder: *mut lzma_lzma1_encoder, + mf: *mut lzma_mf, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + limit: u32, +) -> lzma_ret { + let rc = ::core::ptr::addr_of_mut!((*coder).rc); + if !(*coder).is_initialized && !encode_init(coder, mf) { + return LZMA_OK; + } + if rc_encode(rc, out, out_pos, out_size) { + return LZMA_OK; + } + if (*coder).is_flushed { + return LZMA_STREAM_END; + } + loop { + if limit != UINT32_MAX + && ((*mf).read_pos - (*mf).read_ahead >= limit + || (*out_pos as u64) + rc_pending(rc) >= (LZMA2_CHUNK_MAX - LOOP_INPUT_MAX) as u64) + { + break; + } + if (*mf).read_pos >= (*mf).read_limit { + if (*mf).action == LZMA_RUN { + return LZMA_OK; + } + if (*mf).read_ahead == 0 { + break; + } + } + let mut len: u32 = 0; + let mut back: u32 = 0; + if (*coder).fast_mode { + lzma_lzma_optimum_fast( + coder, + mf, + ::core::ptr::addr_of_mut!(back), + ::core::ptr::addr_of_mut!(len), + ); + } else { + lzma_lzma_optimum_normal( + coder, + mf, + ::core::ptr::addr_of_mut!(back), + ::core::ptr::addr_of_mut!(len), + (*coder).uncomp_size as u32, + ); + } + encode_symbol(coder, mf, back, len, (*coder).uncomp_size as u32); + if out_limit_reached(coder) { + break; + } + (*coder).uncomp_size += len as u64; + if rc_encode(rc, out, out_pos, out_size) { + return LZMA_OK; + } + } + finish_lzma_stream(coder, out, out_pos, out_size) +} +unsafe extern "C" fn lzma_encode( + coder: *mut c_void, + mf: *mut lzma_mf, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, +) -> lzma_ret { + if (*mf).action == LZMA_SYNC_FLUSH { + return LZMA_OPTIONS_ERROR; + } + lzma_lzma_encode( + coder as *mut lzma_lzma1_encoder, + mf, + out, + out_pos, + out_size, + UINT32_MAX, + ) +} +unsafe extern "C" fn lzma_lzma_set_out_limit( + coder_ptr: *mut c_void, + uncomp_size: *mut u64, + out_limit: u64, +) -> lzma_ret { + if out_limit < 6 { + return LZMA_BUF_ERROR; + } + let coder: *mut lzma_lzma1_encoder = coder_ptr as *mut lzma_lzma1_encoder; + (*coder).out_limit = out_limit; + (*coder).uncomp_size_ptr = uncomp_size; + (*coder).use_eopm = false; + LZMA_OK +} +extern "C" fn is_options_valid(options: *const lzma_options_lzma) -> bool { + unsafe { + is_lclppb_valid(options) + && (*options).nice_len >= MATCH_LEN_MIN + && (*options).nice_len <= MATCH_LEN_MAX + && ((*options).mode == LZMA_MODE_FAST || (*options).mode == LZMA_MODE_NORMAL) + } +} +extern "C" fn set_lz_options(lz_options: *mut lzma_lz_options, options: *const lzma_options_lzma) { + unsafe { + (*lz_options).before_size = OPTS as size_t; + (*lz_options).dict_size = (*options).dict_size as size_t; + (*lz_options).after_size = LOOP_INPUT_MAX as size_t; + (*lz_options).match_len_max = MATCH_LEN_MAX as size_t; + (*lz_options).nice_len = (if mf_get_hash_bytes((*options).mf) > (*options).nice_len { + mf_get_hash_bytes((*options).mf) + } else { + (*options).nice_len + }) as size_t; + (*lz_options).match_finder = (*options).mf; + (*lz_options).depth = (*options).depth; + (*lz_options).preset_dict = (*options).preset_dict; + (*lz_options).preset_dict_size = (*options).preset_dict_size; + } +} +unsafe fn length_encoder_reset( + lencoder: *mut lzma_length_encoder, + num_pos_states: u32, + fast_mode: bool, +) { + (*lencoder).choice = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*lencoder).choice2 = (RC_BIT_MODEL_TOTAL >> 1) as probability; + let mut pos_state: size_t = 0; + while pos_state < num_pos_states as size_t { + let mut bt_i: u32 = 0; + while bt_i < (1 << 3) as u32 { + (*lencoder).low[pos_state as usize][bt_i as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i += 1; + } + let mut bt_i_0: u32 = 0; + while bt_i_0 < (1 << 3) as u32 { + (*lencoder).mid[pos_state as usize][bt_i_0 as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_0 += 1; + } + pos_state += 1; + } + let mut bt_i_1: u32 = 0; + while bt_i_1 < (1 << 8) as u32 { + (*lencoder).high[bt_i_1 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_1 += 1; + } + if !fast_mode { + let mut pos_state_0: u32 = 0; + while pos_state_0 < num_pos_states { + length_update_prices(lencoder, pos_state_0); + pos_state_0 += 1; + } + } +} +pub unsafe fn lzma_lzma_encoder_reset( + coder: *mut lzma_lzma1_encoder, + options: *const lzma_options_lzma, +) -> lzma_ret { + if !is_options_valid(options) { + return LZMA_OPTIONS_ERROR; + } + (*coder).pos_mask = ((1u32 << (*options).pb) - 1) as u32; + (*coder).literal_context_bits = (*options).lc; + (*coder).literal_mask = (0x100u32 << (*options).lp) - (0x100 >> (*options).lc); + rc_reset(::core::ptr::addr_of_mut!((*coder).rc)); + (*coder).state = STATE_LIT_LIT; + let mut i: size_t = 0; + while i < REPS as size_t { + (*coder).reps[i as usize] = 0; + i += 1; + } + literal_init( + ::core::ptr::addr_of_mut!((*coder).literal) as *mut probability, + (*options).lc, + (*options).lp, + ); + let mut i_0: size_t = 0; + while i_0 < STATES as size_t { + let mut j: size_t = 0; + while j <= (*coder).pos_mask as size_t { + (*coder).is_match[i_0 as usize][j as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep0_long[i_0 as usize][j as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + j += 1; + } + (*coder).is_rep[i_0 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep0[i_0 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep1[i_0 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + (*coder).is_rep2[i_0 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + i_0 += 1; + } + let mut i_1: size_t = 0; + while i_1 < (FULL_DISTANCES - DIST_MODEL_END) as size_t { + (*coder).dist_special[i_1 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + i_1 += 1; + } + let mut i_2: size_t = 0; + while i_2 < DIST_STATES as size_t { + let mut bt_i: u32 = 0; + while bt_i < (1 << 6) as u32 { + (*coder).dist_slot[i_2 as usize][bt_i as usize] = + (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i += 1; + } + i_2 += 1; + } + let mut bt_i_0: u32 = 0; + while bt_i_0 < (1 << 4) as u32 { + (*coder).dist_align[bt_i_0 as usize] = (RC_BIT_MODEL_TOTAL >> 1) as probability; + bt_i_0 += 1; + } + length_encoder_reset( + ::core::ptr::addr_of_mut!((*coder).match_len_encoder), + 1 << (*options).pb, + (*coder).fast_mode, + ); + length_encoder_reset( + ::core::ptr::addr_of_mut!((*coder).rep_len_encoder), + 1 << (*options).pb, + (*coder).fast_mode, + ); + (*coder).match_price_count = UINT32_MAX / 2; + (*coder).align_price_count = UINT32_MAX / 2; + (*coder).opts_end_index = 0; + (*coder).opts_current_index = 0; + LZMA_OK +} +pub unsafe fn lzma_lzma_encoder_create( + coder_ptr: *mut *mut c_void, + allocator: *const lzma_allocator, + id: lzma_vli, + options: *const lzma_options_lzma, + lz_options: *mut lzma_lz_options, +) -> lzma_ret { + if (*coder_ptr).is_null() { + *coder_ptr = + crate::alloc::internal_alloc_object::(allocator) as *mut c_void; + if (*coder_ptr).is_null() { + return LZMA_MEM_ERROR; + } + } + let coder: *mut lzma_lzma1_encoder = *coder_ptr as *mut lzma_lzma1_encoder; + match (*options).mode { + 1 => { + (*coder).fast_mode = true; + } + 2 => { + (*coder).fast_mode = false; + if (*options).dict_size > (1u32 << 30) + (1 << 29) { + return LZMA_OPTIONS_ERROR; + } + let mut log_size: u32 = 0; + while 1 << log_size < (*options).dict_size { + log_size += 1; + } + (*coder).dist_table_size = log_size * 2; + let nice_len: u32 = if mf_get_hash_bytes((*options).mf) > (*options).nice_len { + mf_get_hash_bytes((*options).mf) as u32 + } else { + (*options).nice_len + }; + (*coder).match_len_encoder.table_size = nice_len + 1 - MATCH_LEN_MIN; + (*coder).rep_len_encoder.table_size = nice_len + 1 - MATCH_LEN_MIN; + } + _ => return LZMA_OPTIONS_ERROR, + } + (*coder).is_initialized = !(*options).preset_dict.is_null() && (*options).preset_dict_size > 0; + (*coder).is_flushed = false; + (*coder).uncomp_size = 0; + (*coder).uncomp_size_ptr = core::ptr::null_mut(); + (*coder).out_limit = 0; + (*coder).use_eopm = id == LZMA_FILTER_LZMA1; + if id == LZMA_FILTER_LZMA1EXT { + if (*options).ext_flags & !(LZMA_LZMA1EXT_ALLOW_EOPM as u32) != 0 { + return LZMA_OPTIONS_ERROR; + } + (*coder).use_eopm = (*options).ext_flags & LZMA_LZMA1EXT_ALLOW_EOPM as u32 != 0; + } + set_lz_options(lz_options, options); + lzma_lzma_encoder_reset(coder, options) +} +unsafe extern "C" fn lzma_encoder_init( + lz: *mut lzma_lz_encoder, + allocator: *const lzma_allocator, + id: lzma_vli, + options: *const c_void, + lz_options: *mut lzma_lz_options, +) -> lzma_ret { + if options.is_null() { + return LZMA_PROG_ERROR; + } + (*lz).code = Some( + lzma_encode + as unsafe extern "C" fn( + *mut c_void, + *mut lzma_mf, + *mut u8, + *mut size_t, + size_t, + ) -> lzma_ret, + ); + (*lz).set_out_limit = Some( + lzma_lzma_set_out_limit as unsafe extern "C" fn(*mut c_void, *mut u64, u64) -> lzma_ret, + ); + lzma_lzma_encoder_create( + ::core::ptr::addr_of_mut!((*lz).coder), + allocator, + id, + options as *const lzma_options_lzma, + lz_options, + ) +} +pub unsafe extern "C" fn lzma_lzma_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + lzma_lz_encoder_init( + next, + allocator, + filters, + Some( + lzma_encoder_init + as unsafe extern "C" fn( + *mut lzma_lz_encoder, + *const lzma_allocator, + lzma_vli, + *const c_void, + *mut lzma_lz_options, + ) -> lzma_ret, + ), + ) +} +pub extern "C" fn lzma_lzma_encoder_memusage(options: *const c_void) -> u64 { + if !is_options_valid(options as *const lzma_options_lzma) { + return UINT64_MAX; + } + let mut lz_options: lzma_lz_options = lzma_lz_options { + before_size: 0, + dict_size: 0, + after_size: 0, + match_len_max: 0, + nice_len: 0, + match_finder: 0, + depth: 0, + preset_dict: core::ptr::null(), + preset_dict_size: 0, + }; + set_lz_options( + ::core::ptr::addr_of_mut!(lz_options), + options as *const lzma_options_lzma, + ); + let lz_memusage: u64 = lzma_lz_encoder_memusage(::core::ptr::addr_of_mut!(lz_options)) as u64; + if lz_memusage == UINT64_MAX { + return UINT64_MAX; + } + (core::mem::size_of::() as u64) + lz_memusage +} +pub unsafe fn lzma_lzma_lclppb_encode(options: *const lzma_options_lzma, byte: *mut u8) -> bool { + if !is_lclppb_valid(options) { + return true; + } + *byte = (((*options).pb * 5 + (*options).lp) * 9 + (*options).lc) as u8; + false +} +pub unsafe extern "C" fn lzma_lzma_props_encode(options: *const c_void, out: *mut u8) -> lzma_ret { + if options.is_null() { + return LZMA_PROG_ERROR; + } + let opt: *const lzma_options_lzma = options as *const lzma_options_lzma; + if lzma_lzma_lclppb_encode(opt, out) { + return LZMA_PROG_ERROR; + } + write32le(out.offset(1), (*opt).dict_size); + LZMA_OK +} +pub fn lzma_mode_is_supported(mode: lzma_mode) -> lzma_bool { + (mode == LZMA_MODE_FAST || mode == LZMA_MODE_NORMAL) as lzma_bool +} diff --git a/liblzma-rs/src/lzma/lzma_encoder_optimum_fast.rs b/liblzma-rs/src/lzma/lzma_encoder_optimum_fast.rs new file mode 100644 index 00000000..d1baa1b1 --- /dev/null +++ b/liblzma-rs/src/lzma/lzma_encoder_optimum_fast.rs @@ -0,0 +1,169 @@ +use crate::lzma::lzma_encoder::MATCH_LEN_MAX; +use crate::types::*; + +#[inline(always)] +unsafe fn not_equal_16(a: *const u8, b: *const u8) -> bool { + core::ptr::read_unaligned(a as *const u16) != core::ptr::read_unaligned(b as *const u16) +} + +#[inline(always)] +fn change_pair(small_dist: u32, big_dist: u32) -> bool { + (big_dist >> 7) > small_dist +} + +#[inline(always)] +unsafe fn coder_match(coder: *const lzma_lzma1_encoder, index: u32) -> *const lzma_match { + debug_assert!((index as usize) < (*coder).matches.len()); + (::core::ptr::addr_of!((*coder).matches) as *const lzma_match).add(index as usize) +} + +#[inline(always)] +unsafe fn mf_find_callback( + mf: *const lzma_mf, +) -> unsafe extern "C" fn(*mut lzma_mf, *mut lzma_match) -> u32 { + debug_assert!((*mf).find.is_some()); + match (*mf).find { + Some(find) => find, + None => core::hint::unreachable_unchecked(), + } +} + +#[inline(always)] +unsafe fn mf_skip_callback(mf: *const lzma_mf) -> unsafe extern "C" fn(*mut lzma_mf, u32) -> () { + debug_assert!((*mf).skip.is_some()); + match (*mf).skip { + Some(skip) => skip, + None => core::hint::unreachable_unchecked(), + } +} + +pub unsafe fn lzma_lzma_optimum_fast( + coder: *mut lzma_lzma1_encoder, + mf: *mut lzma_mf, + back_res: *mut u32, + len_res: *mut u32, +) { + let mf_find = mf_find_callback(mf); + let mf_skip = mf_skip_callback(mf); + let nice_len: u32 = (*mf).nice_len; + let mut len_main: u32 = 0; + let mut matches_count: u32 = 0; + if (*mf).read_ahead == 0 { + len_main = lzma_mf_find_raw( + mf, + ::core::ptr::addr_of_mut!(matches_count), + ::core::ptr::addr_of_mut!((*coder).matches) as *mut lzma_match, + mf_find, + ); + } else { + debug_assert!((*mf).read_ahead == 1); + len_main = (*coder).longest_match_length; + matches_count = (*coder).matches_count; + } + let mut buf: *const u8 = mf_ptr(mf).offset(-1); + let buf_avail: u32 = core::cmp::min(mf_avail(mf) + 1, MATCH_LEN_MAX); + if buf_avail < 2 { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + let mut rep_len: u32 = 0; + let mut rep_index: u32 = 0; + let mut i: u32 = 0; + while i < REPS { + let buf_back: *const u8 = buf.offset(-((*coder).reps[i as usize] as isize)).offset(-1); + if not_equal_16(buf, buf_back) { + i += 1; + continue; + } + let len: u32 = lzma_memcmplen(buf, buf_back, 2, buf_avail) as u32; + if len >= nice_len { + *back_res = i; + *len_res = len; + mf_skip_raw(mf, len - 1, mf_skip); + return; + } + if len > rep_len { + rep_index = i; + rep_len = len; + } + i += 1; + } + if len_main >= nice_len { + *back_res = (*coder_match(coder, matches_count - 1)).dist + REPS; + *len_res = len_main; + mf_skip_raw(mf, len_main - 1, mf_skip); + return; + } + let mut back_main: u32 = 0; + if len_main >= 2 { + back_main = (*coder_match(coder, matches_count - 1)).dist; + while matches_count > 1 && len_main == (*coder_match(coder, matches_count - 2)).len + 1 { + if !change_pair((*coder_match(coder, matches_count - 2)).dist, back_main) { + break; + } + matches_count -= 1; + len_main = (*coder_match(coder, matches_count - 1)).len; + back_main = (*coder_match(coder, matches_count - 1)).dist; + } + if len_main == 2 && back_main >= 0x80 { + len_main = 1; + } + } + if rep_len >= 2 { + if rep_len + 1 >= len_main + || rep_len + 2 >= len_main && back_main > 1 << 9 + || rep_len + 3 >= len_main && back_main > 1 << 15 + { + *back_res = rep_index; + *len_res = rep_len; + mf_skip_raw(mf, rep_len - 1, mf_skip); + return; + } + } + if len_main < 2 || buf_avail <= 2 { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + (*coder).longest_match_length = lzma_mf_find_raw( + mf, + ::core::ptr::addr_of_mut!((*coder).matches_count), + ::core::ptr::addr_of_mut!((*coder).matches) as *mut lzma_match, + mf_find, + ); + if (*coder).longest_match_length >= 2 { + let new_dist: u32 = (*coder_match(coder, (*coder).matches_count - 1)).dist; + if (*coder).longest_match_length >= len_main && new_dist < back_main + || (*coder).longest_match_length == len_main + 1 && !change_pair(back_main, new_dist) + || (*coder).longest_match_length > len_main + 1 + || (*coder).longest_match_length + 1 >= len_main + && len_main >= 3 + && change_pair(new_dist, back_main) + { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + } + buf = buf.offset(1); + let limit: u32 = core::cmp::max(2, len_main - 1); + let mut i_0: u32 = 0; + while i_0 < REPS { + if memcmp( + buf as *const c_void, + buf.offset(-((*coder).reps[i_0 as usize] as isize)) + .offset(-1) as *const c_void, + limit as size_t, + ) == 0 + { + *back_res = UINT32_MAX; + *len_res = 1; + return; + } + i_0 += 1; + } + *back_res = back_main + REPS; + *len_res = len_main; + mf_skip_raw(mf, len_main - 2, mf_skip); +} diff --git a/liblzma-rs/src/lzma/lzma_encoder_optimum_normal.rs b/liblzma-rs/src/lzma/lzma_encoder_optimum_normal.rs new file mode 100644 index 00000000..a00b49f1 --- /dev/null +++ b/liblzma-rs/src/lzma/lzma_encoder_optimum_normal.rs @@ -0,0 +1,1020 @@ +use crate::lzma::lzma_encoder::MATCH_LEN_MAX; +use crate::types::*; +pub const RC_BIT_PRICE_SHIFT_BITS: u32 = 4; +pub const RC_INFINITY_PRICE: c_uint = 1u32 << 30; +#[inline] +unsafe fn rc_bittree_reverse_price( + probs: *const probability, + mut bit_levels: u32, + mut symbol: u32, +) -> u32 { + let mut price: u32 = 0; + let mut model_index: u32 = 1; + loop { + let bit: u32 = symbol & 1; + symbol >>= 1; + price += rc_bit_price(*probs.offset(model_index as isize), bit); + model_index = (model_index << 1) + bit; + bit_levels -= 1; + if bit_levels == 0 { + break; + } + } + price +} +#[inline] +fn rc_direct_price(bits: u32) -> u32 { + bits << RC_BIT_PRICE_SHIFT_BITS +} +#[inline] +unsafe fn get_dist_slot_2(dist: u32) -> u32 { + if dist < 1 << FASTPOS_BITS + (14 / 2 - 1 + 0 * (FASTPOS_BITS - 1)) { + return (lzma_fastpos[(dist >> 14 / 2 - 1 + 0 * (FASTPOS_BITS - 1)) as usize] as u32) + + (2 * (14 / 2 - 1 + 0 * (FASTPOS_BITS - 1))) as u32; + } + if dist < 1 << FASTPOS_BITS + (14 / 2 - 1 + 1 * (FASTPOS_BITS - 1)) { + return (lzma_fastpos[(dist >> 14 / 2 - 1 + 1 * (FASTPOS_BITS - 1)) as usize] as u32) + + (2 * (14 / 2 - 1 + 1 * (FASTPOS_BITS - 1))) as u32; + } + (lzma_fastpos[(dist >> 14 / 2 - 1 + 2 * (FASTPOS_BITS - 1)) as usize] as u32) + + (2 * (14 / 2 - 1 + 2 * (FASTPOS_BITS - 1))) as u32 +} +unsafe fn get_literal_price( + coder: *const lzma_lzma1_encoder, + pos: u32, + prev_byte: u32, + match_mode: bool, + mut match_byte: u32, + mut symbol: u32, +) -> u32 { + let subcoder: *const probability = + (::core::ptr::addr_of!((*coder).literal) as *const probability).offset( + (3u32 * (((pos << 8) + prev_byte) & (*coder).literal_mask) + << (*coder).literal_context_bits) as isize, + ); + let mut price: u32 = 0; + if !match_mode { + price = rc_bittree_price(subcoder, 8, symbol); + } else { + let mut offset: u32 = 0x100; + symbol += 1u32 << 8; + loop { + match_byte <<= 1; + let match_bit: u32 = match_byte & offset; + let subcoder_index: u32 = offset + match_bit + (symbol >> 8); + let bit: u32 = symbol >> 7 & 1; + price += rc_bit_price(*subcoder.offset(subcoder_index as isize), bit); + symbol <<= 1; + offset &= !(match_byte ^ symbol); + if symbol >= 1 << 16 { + break; + } + } + } + price +} +#[inline] +fn get_len_price(lencoder: *const lzma_length_encoder, len: u32, pos_state: u32) -> u32 { + debug_assert!(len >= MATCH_LEN_MIN); + unsafe { + let prices = ::core::ptr::addr_of!((*lencoder).prices) as *const [u32; 272]; + let row = prices.add(pos_state as usize) as *const u32; + *row.add((len - MATCH_LEN_MIN) as usize) + } +} +#[inline] +fn get_short_rep_price( + coder: *const lzma_lzma1_encoder, + state: lzma_lzma_state, + pos_state: u32, +) -> u32 { + unsafe { + rc_bit_0_price(rep0_prob(coder, state)) + + rc_bit_0_price(rep0_long_prob(coder, state, pos_state)) + } +} +#[inline] +fn get_pure_rep_price( + coder: *const lzma_lzma1_encoder, + rep_index: u32, + state: lzma_lzma_state, + pos_state: u32, +) -> u32 { + return unsafe { + let mut price: u32 = 0; + if rep_index == 0 { + price = rc_bit_0_price(rep0_prob(coder, state)); + price += rc_bit_1_price(rep0_long_prob(coder, state, pos_state)); + } else { + price = rc_bit_1_price(rep0_prob(coder, state)); + if rep_index == 1 { + price += rc_bit_0_price(rep1_prob(coder, state)); + } else { + debug_assert!(rep_index >= 2); + price += rc_bit_1_price(rep1_prob(coder, state)); + price += rc_bit_price(rep2_prob(coder, state), rep_index - 2); + } + } + price + }; +} +#[inline] +fn get_rep_price( + coder: *const lzma_lzma1_encoder, + rep_index: u32, + len: u32, + state: lzma_lzma_state, + pos_state: u32, +) -> u32 { + unsafe { + get_len_price( + ::core::ptr::addr_of!((*coder).rep_len_encoder), + len, + pos_state, + ) + get_pure_rep_price(coder, rep_index, state, pos_state) + } +} +#[inline] +fn get_dist_len_price( + coder: *const lzma_lzma1_encoder, + dist: u32, + len: u32, + pos_state: u32, +) -> u32 { + return unsafe { + let dist_state: u32 = if len < (DIST_STATES + MATCH_LEN_MIN) as u32 { + debug_assert!(len >= MATCH_LEN_MIN); + len - MATCH_LEN_MIN + } else { + (DIST_STATES - 1) as u32 + }; + let mut price: u32 = 0; + if dist < FULL_DISTANCES { + price = dist_price(coder, dist_state, dist); + } else { + let dist_slot: u32 = get_dist_slot_2(dist) as u32; + price = dist_slot_price(coder, dist_state, dist_slot) + + align_price(coder, dist & ALIGN_MASK); + } + price += get_len_price( + ::core::ptr::addr_of!((*coder).match_len_encoder), + len, + pos_state, + ); + price + }; +} +#[inline] +fn is_literal_state(state: lzma_lzma_state) -> bool { + state < LIT_STATES +} +#[inline] +fn update_literal_state(state: lzma_lzma_state) -> lzma_lzma_state { + if state <= STATE_SHORTREP_LIT_LIT { + STATE_LIT_LIT + } else if state <= STATE_LIT_SHORTREP { + state - 3 + } else { + state - 6 + } +} +#[inline] +fn update_match_state(state: lzma_lzma_state) -> lzma_lzma_state { + if is_literal_state(state) { + STATE_LIT_MATCH + } else { + STATE_NONLIT_MATCH + } +} +#[inline] +fn update_long_rep_state(state: lzma_lzma_state) -> lzma_lzma_state { + if is_literal_state(state) { + STATE_LIT_LONGREP + } else { + STATE_NONLIT_REP + } +} +#[inline] +fn update_short_rep_state(state: lzma_lzma_state) -> lzma_lzma_state { + if is_literal_state(state) { + STATE_LIT_SHORTREP + } else { + STATE_NONLIT_REP + } +} +#[inline] +unsafe fn not_equal_16(a: *const u8, b: *const u8) -> bool { + core::ptr::read_unaligned(a as *const u16) != core::ptr::read_unaligned(b as *const u16) +} +unsafe fn fill_dist_prices(coder: *mut lzma_lzma1_encoder) { + let mut dist_state: u32 = 0; + while dist_state < DIST_STATES { + let dist_slot_prices: *mut u32 = + ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!((*coder).dist_slot_prices) + as *mut [u32; 64]) + .offset(dist_state as isize)) as *mut u32; + let mut dist_slot: u32 = 0; + while dist_slot < (*coder).dist_table_size { + *dist_slot_prices.offset(dist_slot as isize) = rc_bittree_price( + ::core::ptr::addr_of_mut!(*(::core::ptr::addr_of_mut!((*coder).dist_slot) + as *mut [probability; 64]) + .offset(dist_state as isize)) as *mut probability, + DIST_SLOT_BITS, + dist_slot, + ); + dist_slot += 1; + } + let mut dist_slot_0: u32 = DIST_MODEL_END; + while dist_slot_0 < (*coder).dist_table_size { + *dist_slot_prices.offset(dist_slot_0 as isize) += + rc_direct_price(((dist_slot_0 >> 1) - 1) - ALIGN_BITS); + dist_slot_0 += 1; + } + let mut i: u32 = 0; + while i < DIST_MODEL_START { + (*coder).dist_prices[dist_state as usize][i as usize] = + *dist_slot_prices.offset(i as isize); + i += 1; + } + dist_state += 1; + } + let mut i_0: u32 = DIST_MODEL_START; + while i_0 < FULL_DISTANCES { + let dist_slot_1: u32 = get_dist_slot(i_0) as u32; + let footer_bits: u32 = (dist_slot_1 >> 1) - 1; + let base: u32 = (2 | dist_slot_1 & 1) << footer_bits; + let price: u32 = rc_bittree_reverse_price( + (::core::ptr::addr_of_mut!((*coder).dist_special) as *mut probability) + .offset(base as isize) + .offset(-(dist_slot_1 as isize)) + .offset(-1), + footer_bits, + i_0 - base, + ) as u32; + let mut dist_state_0: u32 = 0; + while dist_state_0 < DIST_STATES { + (*coder).dist_prices[dist_state_0 as usize][i_0 as usize] = + price + (*coder).dist_slot_prices[dist_state_0 as usize][dist_slot_1 as usize]; + dist_state_0 += 1; + } + i_0 += 1; + } + (*coder).match_price_count = 0; +} +unsafe fn fill_align_prices(coder: *mut lzma_lzma1_encoder) { + let mut i: u32 = 0; + while i < ALIGN_SIZE { + (*coder).align_prices[i as usize] = rc_bittree_reverse_price( + ::core::ptr::addr_of_mut!((*coder).dist_align) as *mut probability, + ALIGN_BITS, + i, + ); + i += 1; + } + (*coder).align_price_count = 0; +} +#[inline(always)] +unsafe fn opts_ptr(coder: *mut lzma_lzma1_encoder) -> *mut lzma_optimal { + ::core::ptr::addr_of_mut!((*coder).opts) as *mut lzma_optimal +} +#[inline(always)] +unsafe fn matches_ptr(coder: *mut lzma_lzma1_encoder) -> *mut lzma_match { + ::core::ptr::addr_of_mut!((*coder).matches) as *mut lzma_match +} +#[inline(always)] +unsafe fn optimal_backs_ptr(optimal: *mut lzma_optimal) -> *mut u32 { + ::core::ptr::addr_of_mut!((*optimal).backs) as *mut u32 +} +#[inline(always)] +unsafe fn match_prob( + coder: *const lzma_lzma1_encoder, + state: lzma_lzma_state, + pos_state: u32, +) -> probability { + let row = (::core::ptr::addr_of!((*coder).is_match) as *const [probability; 16]) + .add(state as usize) as *const probability; + *row.add(pos_state as usize) +} +#[inline(always)] +unsafe fn rep0_prob(coder: *const lzma_lzma1_encoder, state: lzma_lzma_state) -> probability { + *((::core::ptr::addr_of!((*coder).is_rep0) as *const probability).add(state as usize)) +} +#[inline(always)] +unsafe fn is_rep_prob(coder: *const lzma_lzma1_encoder, state: lzma_lzma_state) -> probability { + *((::core::ptr::addr_of!((*coder).is_rep) as *const probability).add(state as usize)) +} +#[inline(always)] +unsafe fn rep0_long_prob( + coder: *const lzma_lzma1_encoder, + state: lzma_lzma_state, + pos_state: u32, +) -> probability { + let row = (::core::ptr::addr_of!((*coder).is_rep0_long) as *const [probability; 16]) + .add(state as usize) as *const probability; + *row.add(pos_state as usize) +} +#[inline(always)] +unsafe fn rep1_prob(coder: *const lzma_lzma1_encoder, state: lzma_lzma_state) -> probability { + *((::core::ptr::addr_of!((*coder).is_rep1) as *const probability).add(state as usize)) +} +#[inline(always)] +unsafe fn rep2_prob(coder: *const lzma_lzma1_encoder, state: lzma_lzma_state) -> probability { + *((::core::ptr::addr_of!((*coder).is_rep2) as *const probability).add(state as usize)) +} +#[inline(always)] +unsafe fn dist_slot_price( + coder: *const lzma_lzma1_encoder, + dist_state: u32, + dist_slot: u32, +) -> u32 { + let row = (::core::ptr::addr_of!((*coder).dist_slot_prices) as *const [u32; 64]) + .add(dist_state as usize) as *const u32; + *row.add(dist_slot as usize) +} +#[inline(always)] +unsafe fn dist_price(coder: *const lzma_lzma1_encoder, dist_state: u32, dist: u32) -> u32 { + let row = (::core::ptr::addr_of!((*coder).dist_prices) as *const [u32; 128]) + .add(dist_state as usize) as *const u32; + *row.add(dist as usize) +} +#[inline(always)] +unsafe fn align_price(coder: *const lzma_lzma1_encoder, index: u32) -> u32 { + *((::core::ptr::addr_of!((*coder).align_prices) as *const u32).add(index as usize)) +} +#[inline] +unsafe fn make_literal(optimal: *mut lzma_optimal) { + (*optimal).back_prev = UINT32_MAX; + (*optimal).prev_1_is_literal = false; +} +#[inline] +unsafe fn make_short_rep(optimal: *mut lzma_optimal) { + (*optimal).back_prev = 0; + (*optimal).prev_1_is_literal = false; +} +unsafe fn backward( + coder: *mut lzma_lzma1_encoder, + len_res: *mut u32, + back_res: *mut u32, + mut cur: u32, +) { + let opts = opts_ptr(coder); + (*coder).opts_end_index = cur; + let mut pos_mem: u32 = (*opts.add(cur as usize)).pos_prev; + let mut back_mem: u32 = (*opts.add(cur as usize)).back_prev; + loop { + if (*opts.add(cur as usize)).prev_1_is_literal { + make_literal(opts.add(pos_mem as usize)); + debug_assert!(pos_mem > 0); + let literal_pos_prev = pos_mem - 1; + (*opts.add(pos_mem as usize)).pos_prev = literal_pos_prev; + if (*opts.add(cur as usize)).prev_2 { + (*opts.add(literal_pos_prev as usize)).prev_1_is_literal = false; + (*opts.add(literal_pos_prev as usize)).pos_prev = + (*opts.add(cur as usize)).pos_prev_2; + (*opts.add(literal_pos_prev as usize)).back_prev = + (*opts.add(cur as usize)).back_prev_2; + } + } + let pos_prev: u32 = pos_mem; + let back_cur: u32 = back_mem; + back_mem = (*opts.add(pos_prev as usize)).back_prev; + pos_mem = (*opts.add(pos_prev as usize)).pos_prev; + (*opts.add(pos_prev as usize)).back_prev = back_cur; + (*opts.add(pos_prev as usize)).pos_prev = cur; + cur = pos_prev; + if cur == 0 { + break; + } + } + (*coder).opts_current_index = (*opts).pos_prev; + *len_res = (*opts).pos_prev; + *back_res = (*opts).back_prev; +} +#[inline] +unsafe fn helper1( + coder: *mut lzma_lzma1_encoder, + mf: *mut lzma_mf, + back_res: *mut u32, + len_res: *mut u32, + position: u32, +) -> u32 { + let opts = opts_ptr(coder); + let matches = matches_ptr(coder); + let nice_len: u32 = (*mf).nice_len; + let mut len_main: u32 = 0; + let mut matches_count: u32 = 0; + if (*mf).read_ahead == 0 { + len_main = lzma_mf_find(mf, ::core::ptr::addr_of_mut!(matches_count), matches); + } else { + debug_assert!((*mf).read_ahead == 1); + len_main = (*coder).longest_match_length; + matches_count = (*coder).matches_count; + } + let buf_avail: u32 = core::cmp::min(mf_avail(mf) + 1, MATCH_LEN_MAX); + if buf_avail < 2 { + *back_res = UINT32_MAX; + *len_res = 1; + return UINT32_MAX; + } + let buf: *const u8 = mf_ptr(mf).offset(-1); + let mut rep_lens: [u32; 4] = [0; 4]; + let rep_lens_ptr = rep_lens.as_mut_ptr(); + let mut rep_max_index: u32 = 0; + let mut i: u32 = 0; + while i < REPS { + let buf_back: *const u8 = buf.offset(-((*coder).reps[i as usize] as isize)).offset(-1); + if not_equal_16(buf, buf_back) { + *rep_lens_ptr.add(i as usize) = 0; + } else { + *rep_lens_ptr.add(i as usize) = lzma_memcmplen(buf, buf_back, 2, buf_avail); + if *rep_lens_ptr.add(i as usize) > *rep_lens_ptr.add(rep_max_index as usize) { + rep_max_index = i; + } + } + i += 1; + } + if *rep_lens_ptr.add(rep_max_index as usize) >= nice_len { + *back_res = rep_max_index; + *len_res = *rep_lens_ptr.add(rep_max_index as usize); + mf_skip(mf, *len_res - 1); + return UINT32_MAX; + } + if len_main >= nice_len { + debug_assert!(matches_count > 0); + *back_res = (*matches.add((matches_count - 1) as usize)).dist + REPS; + *len_res = len_main; + mf_skip(mf, len_main - 1); + return UINT32_MAX; + } + let current_byte: u8 = *buf; + let match_byte: u8 = *buf.offset(-((*coder).reps[0] as isize)).offset(-1); + if len_main < 2 && current_byte != match_byte && *rep_lens_ptr.add(rep_max_index as usize) < 2 { + *back_res = UINT32_MAX; + *len_res = 1; + return UINT32_MAX; + } + (*opts).state = (*coder).state; + let pos_state: u32 = position & (*coder).pos_mask; + (*opts.add(1)).price = rc_bit_0_price(match_prob(coder, (*coder).state, pos_state)) + + get_literal_price( + coder, + position, + *buf.offset(-1) as u32, + !(((*coder).state as u32) < LIT_STATES), + match_byte as u32, + current_byte as u32, + ); + make_literal(opts.add(1)); + let match_price: u32 = rc_bit_1_price(match_prob(coder, (*coder).state, pos_state)) as u32; + let rep_match_price: u32 = + match_price + rc_bit_1_price(is_rep_prob(coder, (*coder).state)) as u32; + if match_byte == current_byte { + let short_rep_price: u32 = + rep_match_price + get_short_rep_price(coder, (*coder).state, pos_state) as u32; + if short_rep_price < (*opts.add(1)).price { + (*opts.add(1)).price = short_rep_price; + make_short_rep(opts.add(1)); + } + } + let len_end: u32 = core::cmp::max(len_main, *rep_lens_ptr.add(rep_max_index as usize)); + if len_end < 2 { + *back_res = (*opts.add(1)).back_prev; + *len_res = 1; + return UINT32_MAX; + } + (*opts.add(1)).pos_prev = 0; + let mut i_0: u32 = 0; + while i_0 < REPS { + (*opts).backs[i_0 as usize] = (*coder).reps[i_0 as usize]; + i_0 += 1; + } + let mut len: u32 = len_end; + loop { + (*opts.add(len as usize)).price = RC_INFINITY_PRICE as u32; + len -= 1; + if len < 2 { + break; + } + } + let mut i_1: u32 = 0; + while i_1 < REPS { + let mut rep_len: u32 = *rep_lens_ptr.add(i_1 as usize); + if rep_len >= 2 { + let price: u32 = + rep_match_price + get_pure_rep_price(coder, i_1, (*coder).state, pos_state) as u32; + loop { + let cur_and_len_price: u32 = price + + get_len_price( + ::core::ptr::addr_of_mut!((*coder).rep_len_encoder), + rep_len, + pos_state, + ) as u32; + if cur_and_len_price < (*opts.add(rep_len as usize)).price { + (*opts.add(rep_len as usize)).price = cur_and_len_price; + (*opts.add(rep_len as usize)).pos_prev = 0; + (*opts.add(rep_len as usize)).back_prev = i_1; + (*opts.add(rep_len as usize)).prev_1_is_literal = false; + } + rep_len -= 1; + if rep_len < 2 { + break; + } + } + } + i_1 += 1; + } + let normal_match_price: u32 = + match_price + rc_bit_0_price(is_rep_prob(coder, (*coder).state)) as u32; + len = if *rep_lens_ptr >= 2 { + *rep_lens_ptr + 1 + } else { + 2 + }; + if len <= len_main { + let mut i_2: u32 = 0; + while len > (*matches.add(i_2 as usize)).len { + i_2 += 1; + } + loop { + let dist: u32 = (*matches.add(i_2 as usize)).dist; + let cur_and_len_price_0: u32 = + normal_match_price + get_dist_len_price(coder, dist, len, pos_state) as u32; + if cur_and_len_price_0 < (*opts.add(len as usize)).price { + (*opts.add(len as usize)).price = cur_and_len_price_0; + (*opts.add(len as usize)).pos_prev = 0; + (*opts.add(len as usize)).back_prev = dist + REPS; + (*opts.add(len as usize)).prev_1_is_literal = false; + } + if len == (*matches.add(i_2 as usize)).len { + i_2 += 1; + if i_2 == matches_count { + break; + } + } + len += 1; + } + } + len_end +} +#[inline(never)] +unsafe fn helper2( + coder: *mut lzma_lzma1_encoder, + reps: *mut u32, + buf: *const u8, + mut len_end: u32, + position: u32, + cur: u32, + nice_len: u32, + buf_avail_full: u32, +) -> u32 { + let opts = opts_ptr(coder); + let matches = matches_ptr(coder); + let mut matches_count: u32 = (*coder).matches_count; + let mut new_len: u32 = (*coder).longest_match_length; + let mut pos_prev: u32 = (*opts.add(cur as usize)).pos_prev; + let mut state: lzma_lzma_state = STATE_LIT_LIT; + if (*opts.add(cur as usize)).prev_1_is_literal { + pos_prev -= 1; + if (*opts.add(cur as usize)).prev_2 { + state = (*opts.add((*opts.add(cur as usize)).pos_prev_2 as usize)).state; + if (*opts.add(cur as usize)).back_prev_2 < REPS { + state = update_long_rep_state(state); + } else { + state = update_match_state(state); + } + } else { + state = (*opts.add(pos_prev as usize)).state; + } + state = update_literal_state(state); + } else { + state = (*opts.add(pos_prev as usize)).state; + } + if pos_prev == cur - 1 { + if (*opts.add(cur as usize)).back_prev == 0 { + state = update_short_rep_state(state); + } else { + state = update_literal_state(state); + } + } else { + let mut pos: u32 = 0; + if (*opts.add(cur as usize)).prev_1_is_literal && (*opts.add(cur as usize)).prev_2 { + pos_prev = (*opts.add(cur as usize)).pos_prev_2; + pos = (*opts.add(cur as usize)).back_prev_2; + state = update_long_rep_state(state); + } else { + pos = (*opts.add(cur as usize)).back_prev; + if pos < REPS { + state = update_long_rep_state(state); + } else { + state = update_match_state(state); + } + } + if pos < REPS { + let prev_backs = optimal_backs_ptr(opts.add(pos_prev as usize)); + *reps = *prev_backs.add(pos as usize); + let mut i: u32 = 0; + i = 1; + while i <= pos { + *reps.offset(i as isize) = *prev_backs.add((i - 1) as usize); + i += 1; + } + while i < REPS { + *reps.offset(i as isize) = *prev_backs.add(i as usize); + i += 1; + } + } else { + *reps = pos - REPS; + let prev_backs = optimal_backs_ptr(opts.add(pos_prev as usize)); + let mut i_0: u32 = 1; + while i_0 < REPS { + *reps.offset(i_0 as isize) = *prev_backs.add((i_0 - 1) as usize); + i_0 += 1; + } + } + } + (*opts.add(cur as usize)).state = state; + let cur_backs = optimal_backs_ptr(opts.add(cur as usize)); + let mut i_1: u32 = 0; + while i_1 < REPS { + *cur_backs.add(i_1 as usize) = *reps.offset(i_1 as isize); + i_1 += 1; + } + let cur_price: u32 = (*opts.add(cur as usize)).price; + let current_byte: u8 = *buf; + let match_byte: u8 = *buf.offset(-(*reps as isize)).offset(-1); + let pos_state: u32 = position & (*coder).pos_mask; + let cur_and_1_price: u32 = cur_price + + rc_bit_0_price(match_prob(coder, state, pos_state)) as u32 + + get_literal_price( + coder, + position, + *buf.offset(-1) as u32, + !is_literal_state(state), + match_byte as u32, + current_byte as u32, + ) as u32; + let next_opt = &mut *opts.add((cur + 1) as usize); + let mut next_is_literal: bool = false; + if cur_and_1_price < next_opt.price { + next_opt.price = cur_and_1_price; + next_opt.pos_prev = cur; + make_literal(next_opt); + next_is_literal = true; + } + let match_price: u32 = cur_price + rc_bit_1_price(match_prob(coder, state, pos_state)) as u32; + let rep_match_price: u32 = match_price + rc_bit_1_price(is_rep_prob(coder, state)) as u32; + if match_byte == current_byte && !(next_opt.pos_prev < cur && next_opt.back_prev == 0) { + let short_rep_price: u32 = + rep_match_price + get_short_rep_price(coder, state, pos_state) as u32; + if short_rep_price <= next_opt.price { + next_opt.price = short_rep_price; + next_opt.pos_prev = cur; + make_short_rep(next_opt); + next_is_literal = true; + } + } + if buf_avail_full < 2 { + return len_end; + } + let buf_avail: u32 = if buf_avail_full < nice_len { + buf_avail_full + } else { + nice_len + }; + if !next_is_literal && match_byte != current_byte { + let buf_back: *const u8 = buf.offset(-(*reps as isize)).offset(-1); + let limit: u32 = if buf_avail_full < nice_len + 1 { + buf_avail_full + } else { + nice_len + 1 + }; + let len_test: u32 = (lzma_memcmplen(buf, buf_back, 1, limit) as u32) - 1; + if len_test >= 2 { + let state_2: lzma_lzma_state = update_literal_state(state); + let pos_state_next: u32 = (position + 1) & (*coder).pos_mask; + let next_rep_match_price: u32 = cur_and_1_price + + rc_bit_1_price(match_prob(coder, state_2, pos_state_next)) as u32 + + rc_bit_1_price(is_rep_prob(coder, state_2)) as u32; + let offset: u32 = cur + 1 + len_test; + while len_end < offset { + len_end += 1; + (*opts.add(len_end as usize)).price = RC_INFINITY_PRICE as u32; + } + let cur_and_len_price: u32 = next_rep_match_price + + get_rep_price(coder, 0, len_test, state_2, pos_state_next) as u32; + let opt = opts.add(offset as usize); + if cur_and_len_price < (*opt).price { + (*opt).price = cur_and_len_price; + (*opt).pos_prev = cur + 1; + (*opt).back_prev = 0; + (*opt).prev_1_is_literal = true; + (*opt).prev_2 = false; + } + } + } + let mut start_len: u32 = 2; + let mut rep_index: u32 = 0; + while rep_index < REPS { + let buf_back_0: *const u8 = buf + .offset(-(*reps.offset(rep_index as isize) as isize)) + .offset(-1); + if !not_equal_16(buf, buf_back_0) { + let mut len_test_0: u32 = lzma_memcmplen(buf, buf_back_0, 2, buf_avail); + while len_end < cur + len_test_0 { + len_end += 1; + (*opts.add(len_end as usize)).price = RC_INFINITY_PRICE as u32; + } + let len_test_temp: u32 = len_test_0; + let price: u32 = + rep_match_price + get_pure_rep_price(coder, rep_index, state, pos_state) as u32; + loop { + let cur_and_len_price_0: u32 = price + + get_len_price( + ::core::ptr::addr_of_mut!((*coder).rep_len_encoder), + len_test_0, + pos_state, + ) as u32; + let opt = opts.add((cur + len_test_0) as usize); + if cur_and_len_price_0 < (*opt).price { + (*opt).price = cur_and_len_price_0; + (*opt).pos_prev = cur; + (*opt).back_prev = rep_index; + (*opt).prev_1_is_literal = false; + } + len_test_0 -= 1; + if len_test_0 < 2 { + break; + } + } + len_test_0 = len_test_temp; + if rep_index == 0 { + start_len = len_test_0 + 1; + } + let mut len_test_2: u32 = len_test_0 + 1; + let limit_0: u32 = if buf_avail_full < len_test_2 + nice_len { + buf_avail_full + } else { + len_test_2 + nice_len + }; + if len_test_2 < limit_0 { + len_test_2 = lzma_memcmplen(buf, buf_back_0, len_test_2, limit_0); + } + len_test_2 -= len_test_0 + 1; + if len_test_2 >= 2 { + consider_literal_after_rep( + coder, + opts, + ::core::ptr::addr_of_mut!(len_end), + buf, + buf_back_0, + position, + cur, + len_test_0, + len_test_2, + price, + state, + pos_state, + rep_index, + ); + } + } + rep_index += 1; + } + if new_len > buf_avail { + new_len = buf_avail; + matches_count = 0; + while new_len > (*matches.add(matches_count as usize)).len { + matches_count += 1; + } + (*matches.add(matches_count as usize)).len = new_len; + matches_count += 1; + } + if new_len >= start_len { + let normal_match_price: u32 = + match_price + rc_bit_0_price(is_rep_prob(coder, state)) as u32; + while len_end < cur + new_len { + len_end += 1; + (*opts.add(len_end as usize)).price = RC_INFINITY_PRICE as u32; + } + let mut i_2: u32 = 0; + while start_len > (*matches.add(i_2 as usize)).len { + i_2 += 1; + } + let mut len_test_1: u32 = start_len; + loop { + let cur_back: u32 = (*matches.add(i_2 as usize)).dist; + let cur_and_len_price_2: u32 = + normal_match_price + get_dist_len_price(coder, cur_back, len_test_1, pos_state); + let opt = opts.add((cur + len_test_1) as usize); + if cur_and_len_price_2 < (*opt).price { + (*opt).price = cur_and_len_price_2; + (*opt).pos_prev = cur; + (*opt).back_prev = cur_back + REPS; + (*opt).prev_1_is_literal = false; + } + if len_test_1 == (*matches.add(i_2 as usize)).len { + let buf_back_1: *const u8 = buf.offset(-(cur_back as isize)).offset(-1); + let mut len_test_2_0: u32 = len_test_1 + 1; + let limit_1: u32 = if buf_avail_full < len_test_2_0 + nice_len { + buf_avail_full + } else { + len_test_2_0 + nice_len + }; + if len_test_2_0 < limit_1 { + len_test_2_0 = lzma_memcmplen(buf, buf_back_1, len_test_2_0, limit_1); + } + len_test_2_0 -= len_test_1 + 1; + if len_test_2_0 >= 2 { + consider_literal_after_match( + coder, + opts, + ::core::ptr::addr_of_mut!(len_end), + buf, + buf_back_1, + position, + cur, + len_test_1, + len_test_2_0, + cur_and_len_price_2, + state, + cur_back, + ); + } + i_2 += 1; + if i_2 == matches_count { + break; + } + } + len_test_1 += 1; + } + } + len_end +} +#[cold] +#[inline(never)] +unsafe fn consider_literal_after_rep( + coder: *mut lzma_lzma1_encoder, + opts: *mut lzma_optimal, + len_end: *mut u32, + buf: *const u8, + buf_back: *const u8, + position: u32, + cur: u32, + len_test: u32, + len_test_2: u32, + price: u32, + state: lzma_lzma_state, + pos_state: u32, + rep_index: u32, +) { + let mut state_2: lzma_lzma_state = state; + state_2 = update_long_rep_state(state_2); + let mut pos_state_next: u32 = (position + len_test) & (*coder).pos_mask; + let cur_and_len_literal_price: u32 = price + + get_len_price( + ::core::ptr::addr_of_mut!((*coder).rep_len_encoder), + len_test, + pos_state, + ) as u32 + + rc_bit_0_price(match_prob(coder, state_2, pos_state_next)) as u32 + + get_literal_price( + coder, + position + len_test, + *buf.offset((len_test - 1) as isize) as u32, + true, + *buf_back.offset(len_test as isize) as u32, + *buf.offset(len_test as isize) as u32, + ) as u32; + state_2 = update_literal_state(state_2); + pos_state_next = (position + len_test + 1) & (*coder).pos_mask; + let next_rep_match_price: u32 = cur_and_len_literal_price + + rc_bit_1_price(match_prob(coder, state_2, pos_state_next)) as u32 + + rc_bit_1_price(is_rep_prob(coder, state_2)) as u32; + let offset: u32 = cur + len_test + 1 + len_test_2; + while *len_end < offset { + *len_end += 1; + (*opts.add(*len_end as usize)).price = RC_INFINITY_PRICE as u32; + } + let cur_and_len_price: u32 = + next_rep_match_price + get_rep_price(coder, 0, len_test_2, state_2, pos_state_next) as u32; + let opt = opts.add(offset as usize); + if cur_and_len_price < (*opt).price { + (*opt).price = cur_and_len_price; + (*opt).pos_prev = cur + len_test + 1; + (*opt).back_prev = 0; + (*opt).prev_1_is_literal = true; + (*opt).prev_2 = true; + (*opt).pos_prev_2 = cur; + (*opt).back_prev_2 = rep_index; + } +} +#[cold] +#[inline(never)] +unsafe fn consider_literal_after_match( + coder: *mut lzma_lzma1_encoder, + opts: *mut lzma_optimal, + len_end: *mut u32, + buf: *const u8, + buf_back: *const u8, + position: u32, + cur: u32, + len_test: u32, + len_test_2: u32, + cur_and_len_price: u32, + state: lzma_lzma_state, + cur_back: u32, +) { + let mut state_2: lzma_lzma_state = state; + state_2 = update_match_state(state_2); + let mut pos_state_next: u32 = (position + len_test) & (*coder).pos_mask; + let cur_and_len_literal_price: u32 = cur_and_len_price + + rc_bit_0_price(match_prob(coder, state_2, pos_state_next)) as u32 + + get_literal_price( + coder, + position + len_test, + *buf.offset((len_test - 1) as isize) as u32, + true, + *buf_back.offset(len_test as isize) as u32, + *buf.offset(len_test as isize) as u32, + ) as u32; + state_2 = update_literal_state(state_2); + pos_state_next = (pos_state_next + 1) & (*coder).pos_mask; + let next_rep_match_price: u32 = cur_and_len_literal_price + + rc_bit_1_price(match_prob(coder, state_2, pos_state_next)) as u32 + + rc_bit_1_price(is_rep_prob(coder, state_2)) as u32; + let offset: u32 = cur + len_test + 1 + len_test_2; + while *len_end < offset { + *len_end += 1; + (*opts.add(*len_end as usize)).price = RC_INFINITY_PRICE as u32; + } + let cur_and_len_price = + next_rep_match_price + get_rep_price(coder, 0, len_test_2, state_2, pos_state_next); + let opt = opts.add(offset as usize); + if cur_and_len_price < (*opt).price { + (*opt).price = cur_and_len_price; + (*opt).pos_prev = cur + len_test + 1; + (*opt).back_prev = 0; + (*opt).prev_1_is_literal = true; + (*opt).prev_2 = true; + (*opt).pos_prev_2 = cur; + (*opt).back_prev_2 = cur_back + REPS; + } +} +pub unsafe fn lzma_lzma_optimum_normal( + coder: *mut lzma_lzma1_encoder, + mf: *mut lzma_mf, + back_res: *mut u32, + len_res: *mut u32, + position: u32, +) { + let opts = opts_ptr(coder); + let matches = matches_ptr(coder); + if (*coder).opts_end_index != (*coder).opts_current_index { + let opt = opts.add((*coder).opts_current_index as usize); + *len_res = (*opt).pos_prev - (*coder).opts_current_index; + *back_res = (*opt).back_prev; + (*coder).opts_current_index = (*opt).pos_prev; + return; + } + if (*mf).read_ahead == 0 { + if (*coder).match_price_count >= (1 << 7) as u32 { + fill_dist_prices(coder); + } + if (*coder).align_price_count >= ALIGN_SIZE { + fill_align_prices(coder); + } + } + let mut len_end: u32 = helper1(coder, mf, back_res, len_res, position); + if len_end == UINT32_MAX { + return; + } + let mut reps: [u32; 4] = (*coder).reps; + let mut cur: u32 = 0; + cur = 1; + while cur < len_end { + (*coder).longest_match_length = lzma_mf_find( + mf, + ::core::ptr::addr_of_mut!((*coder).matches_count), + matches, + ); + if (*coder).longest_match_length >= (*mf).nice_len { + break; + } + len_end = helper2( + coder, + ::core::ptr::addr_of_mut!(reps) as *mut u32, + mf_ptr(mf).offset(-1), + len_end, + position + cur, + cur, + (*mf).nice_len, + if mf_avail(mf) + 1 < ((1 << 12) - 1) as u32 - cur { + mf_avail(mf) + 1 + } else { + ((1 << 12) - 1) as u32 - cur + }, + ); + cur += 1; + } + backward(coder, len_res, back_res, cur); +} diff --git a/liblzma-rs/src/lzma/lzma_encoder_presets.rs b/liblzma-rs/src/lzma/lzma_encoder_presets.rs new file mode 100644 index 00000000..098a8363 --- /dev/null +++ b/liblzma-rs/src/lzma/lzma_encoder_presets.rs @@ -0,0 +1,50 @@ +use crate::types::*; +pub const LZMA_LC_DEFAULT: u32 = 3; +pub const LZMA_LP_DEFAULT: u32 = 0; +pub const LZMA_PB_DEFAULT: u32 = 2; +pub const LZMA_PRESET_LEVEL_MASK: c_uint = 0x1f; +pub unsafe fn lzma_lzma_preset(options: *mut lzma_options_lzma, preset: u32) -> lzma_bool { + let level: u32 = preset & LZMA_PRESET_LEVEL_MASK as u32; + let flags: u32 = preset & !(LZMA_PRESET_LEVEL_MASK as u32); + let supported_flags: u32 = LZMA_PRESET_EXTREME as u32; + if level > 9 || flags & !supported_flags != 0 { + return true as lzma_bool; + } + (*options).preset_dict = core::ptr::null(); + (*options).preset_dict_size = 0; + (*options).lc = LZMA_LC_DEFAULT; + (*options).lp = LZMA_LP_DEFAULT; + (*options).pb = LZMA_PB_DEFAULT; + static mut dict_pow2: [u8; 10] = [18, 20, 21, 22, 22, 23, 23, 24, 25, 26]; + (*options).dict_size = 1u32 << dict_pow2[level as usize]; + if level <= 3 { + (*options).mode = LZMA_MODE_FAST; + (*options).mf = (if level == 0 { LZMA_MF_HC3 } else { LZMA_MF_HC4 }) as lzma_match_finder; + (*options).nice_len = (if level <= 1 { 128 } else { 273 }) as u32; + static mut depths: [u8; 4] = [4, 8, 24, 48]; + (*options).depth = depths[level as usize] as u32; + } else { + (*options).mode = LZMA_MODE_NORMAL; + (*options).mf = LZMA_MF_BT4; + (*options).nice_len = (if level == 4 { + 16 + } else if level == 5 { + 32 + } else { + 64 + }) as u32; + (*options).depth = 0; + } + if flags & LZMA_PRESET_EXTREME as u32 != 0 { + (*options).mode = LZMA_MODE_NORMAL; + (*options).mf = LZMA_MF_BT4; + if level == 3 || level == 5 { + (*options).nice_len = 192; + (*options).depth = 0; + } else { + (*options).nice_len = 273; + (*options).depth = 512; + } + } + false as lzma_bool +} diff --git a/liblzma-rs/src/lzma/mod.rs b/liblzma-rs/src/lzma/mod.rs new file mode 100644 index 00000000..0a3c817d --- /dev/null +++ b/liblzma-rs/src/lzma/mod.rs @@ -0,0 +1,8 @@ +pub mod fastpos_table; +pub mod lzma2_decoder; +pub mod lzma2_encoder; +pub mod lzma_decoder; +pub mod lzma_encoder; +pub mod lzma_encoder_optimum_fast; +pub mod lzma_encoder_optimum_normal; +pub mod lzma_encoder_presets; diff --git a/liblzma-rs/src/rangecoder/mod.rs b/liblzma-rs/src/rangecoder/mod.rs new file mode 100644 index 00000000..f6f18e9e --- /dev/null +++ b/liblzma-rs/src/rangecoder/mod.rs @@ -0,0 +1 @@ +pub mod price_table; diff --git a/liblzma-rs/src/rangecoder/price_table.rs b/liblzma-rs/src/rangecoder/price_table.rs new file mode 100644 index 00000000..10ce0f46 --- /dev/null +++ b/liblzma-rs/src/rangecoder/price_table.rs @@ -0,0 +1,7 @@ +pub static mut lzma_rc_prices: [u8; 128] = [ + 128, 103, 91, 84, 78, 73, 69, 66, 63, 61, 58, 56, 54, 52, 51, 49, 48, 46, 45, 44, 43, 42, 41, + 40, 39, 38, 37, 36, 35, 34, 34, 33, 32, 31, 31, 30, 29, 29, 28, 28, 27, 26, 26, 25, 25, 24, 24, + 23, 23, 22, 22, 22, 21, 21, 20, 20, 19, 19, 19, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, + 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, + 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, +]; diff --git a/liblzma-rs/src/simple/arm.rs b/liblzma-rs/src/simple/arm.rs new file mode 100644 index 00000000..bb184fdc --- /dev/null +++ b/liblzma-rs/src/simple/arm.rs @@ -0,0 +1,70 @@ +use crate::types::*; +unsafe extern "C" fn arm_code( + _simple: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + size &= !(3); + let mut i: size_t = 0; + i = 0; + while i < size { + if *buffer.offset((i + 3) as isize) == 0xeb { + let mut src: u32 = (*buffer.offset((i + 2) as isize) as u32) << 16 + | (*buffer.offset((i + 1) as isize) as u32) << 8 + | *buffer.offset(i as isize) as u32; + src <<= 2; + let mut dest: u32 = 0; + if is_encoder { + dest = now_pos + .wrapping_add(i as u32) + .wrapping_add(8) + .wrapping_add(src); + } else { + dest = src.wrapping_sub(now_pos.wrapping_add(i as u32).wrapping_add(8)); + } + dest >>= 2; + *buffer.offset((i + 2) as isize) = (dest >> 16) as u8; + *buffer.offset((i + 1) as isize) = (dest >> 8) as u8; + *buffer.offset(i as isize) = dest as u8; + } + i += 4; + } + i +} +extern "C" fn arm_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + unsafe { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + arm_code as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 4, + 4, + is_encoder, + ) + } +} +pub unsafe extern "C" fn lzma_simple_arm_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + arm_coder_init(next, allocator, filters, true) +} +pub unsafe extern "C" fn lzma_simple_arm_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + arm_coder_init(next, allocator, filters, false) +} diff --git a/liblzma-rs/src/simple/arm64.rs b/liblzma-rs/src/simple/arm64.rs new file mode 100644 index 00000000..f9f5c934 --- /dev/null +++ b/liblzma-rs/src/simple/arm64.rs @@ -0,0 +1,86 @@ +use crate::types::*; +unsafe extern "C" fn arm64_code( + _simple: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + size &= !(3); + let mut i: size_t = 0; + i = 0; + while i < size { + let mut pc: u32 = now_pos.wrapping_add(i as u32); + let mut instr: u32 = read32le(buffer.offset(i as isize)); + if instr >> 26 == 0x25 { + let src: u32 = instr; + instr = 0x94000000; + pc >>= 2; + if !is_encoder { + pc = 0u32.wrapping_sub(pc); + } + instr |= src.wrapping_add(pc) & 0x3ffffff; + write32le(buffer.offset(i as isize), instr); + } else if instr & 0x9f000000 == 0x90000000 { + let src_0: u32 = instr >> 29 & 3 | instr >> 3 & 0x1ffffc; + if src_0.wrapping_add(0x20000) & 0x1c0000 == 0 { + instr = (instr & 0x9000001f) as u32; + pc >>= 12; + if !is_encoder { + pc = 0u32.wrapping_sub(pc); + } + let dest: u32 = src_0.wrapping_add(pc); + instr |= (dest & 3) << 29; + instr |= (dest & 0x3fffc) << 3; + instr = (instr | (0u32.wrapping_sub(dest & 0x20000) & 0xe00000)) as u32; + write32le(buffer.offset(i as isize), instr); + } + } + i += 4; + } + i +} +extern "C" fn arm64_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + unsafe { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + arm64_code + as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 4, + 4, + is_encoder, + ) + } +} +pub unsafe extern "C" fn lzma_simple_arm64_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + arm64_coder_init(next, allocator, filters, true) +} +pub unsafe fn lzma_bcj_arm64_encode(mut start_offset: u32, buf: *mut u8, size: size_t) -> size_t { + start_offset = (start_offset & !3u32) as u32; + arm64_code(core::ptr::null_mut(), start_offset, true, buf, size) +} +pub unsafe extern "C" fn lzma_simple_arm64_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + arm64_coder_init(next, allocator, filters, false) +} +pub unsafe fn lzma_bcj_arm64_decode(mut start_offset: u32, buf: *mut u8, size: size_t) -> size_t { + start_offset = (start_offset & !3u32) as u32; + arm64_code(core::ptr::null_mut(), start_offset, false, buf, size) +} diff --git a/liblzma-rs/src/simple/armthumb.rs b/liblzma-rs/src/simple/armthumb.rs new file mode 100644 index 00000000..f17a4b0b --- /dev/null +++ b/liblzma-rs/src/simple/armthumb.rs @@ -0,0 +1,79 @@ +use crate::types::*; +unsafe extern "C" fn armthumb_code( + _simple: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + if size < 4 { + return 0; + } + size -= 4; + let mut i: size_t = 0; + i = 0; + while i <= size { + if *buffer.offset((i + 1) as isize) & 0xf8 == 0xf0 + && *buffer.offset((i + 3) as isize) & 0xf8 == 0xf8 + { + let mut src: u32 = (*buffer.offset((i + 1) as isize) as u32 & 7) << 19 + | (*buffer.offset(i as isize) as u32) << 11 + | (*buffer.offset((i + 3) as isize) as u32 & 7) << 8 + | *buffer.offset((i + 2) as isize) as u32; + src <<= 1; + let mut dest: u32 = 0; + if is_encoder { + dest = now_pos + .wrapping_add(i as u32) + .wrapping_add(4) + .wrapping_add(src); + } else { + dest = src.wrapping_sub(now_pos.wrapping_add(i as u32).wrapping_add(4)); + } + dest >>= 1; + *buffer.offset((i + 1) as isize) = (0xf0 | dest >> 19 & 0x7) as u8; + *buffer.offset(i as isize) = (dest >> 11) as u8; + *buffer.offset((i + 3) as isize) = (0xf8 | dest >> 8 & 0x7) as u8; + *buffer.offset((i + 2) as isize) = dest as u8; + i += 2; + } + i += 2; + } + i +} +extern "C" fn armthumb_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + unsafe { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + armthumb_code + as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 4, + 2, + is_encoder, + ) + } +} +pub unsafe extern "C" fn lzma_simple_armthumb_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + armthumb_coder_init(next, allocator, filters, true) +} +pub unsafe extern "C" fn lzma_simple_armthumb_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + armthumb_coder_init(next, allocator, filters, false) +} diff --git a/liblzma-rs/src/simple/ia64.rs b/liblzma-rs/src/simple/ia64.rs new file mode 100644 index 00000000..aa8a2dfa --- /dev/null +++ b/liblzma-rs/src/simple/ia64.rs @@ -0,0 +1,98 @@ +use crate::types::*; +unsafe extern "C" fn ia64_code( + _simple: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + static mut BRANCH_TABLE: [u32; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, + 0, 0, + ]; + size &= !(15); + let mut i: size_t = 0; + i = 0; + while i < size { + let instr_template: u32 = (*buffer.offset(i as isize) & 0x1f) as u32; + let mask: u32 = BRANCH_TABLE[instr_template as usize]; + let mut bit_pos: u32 = 5; + let mut slot: size_t = 0; + while slot < 3 { + if mask >> slot & 1 != 0 { + let byte_pos: size_t = (bit_pos >> 3) as size_t; + let bit_res: u32 = bit_pos & 0x7; + let mut instruction: u64 = 0; + let mut j: size_t = 0; + while j < 6 { + instruction += (*buffer.offset((i + j + byte_pos) as isize) as u64) << (8 * j); + j += 1; + } + let mut inst_norm: u64 = instruction >> bit_res; + if inst_norm >> 37 & 0xf as u64 == 0x5 as u64 && inst_norm >> 9 & 0x7 as u64 == 0 { + let mut src: u32 = (inst_norm >> 13 & 0xfffff as u64) as u32; + src = (src as u64 | (inst_norm >> 36 & 1) << 20) as u32; + src <<= 4; + let mut dest: u32 = 0; + if is_encoder { + dest = now_pos.wrapping_add(i as u32).wrapping_add(src); + } else { + dest = src.wrapping_sub(now_pos.wrapping_add(i as u32)); + } + dest >>= 4; + inst_norm &= !((0x8fffff as u64) << 13); + inst_norm |= ((dest & 0xfffff) as u64) << 13; + inst_norm |= ((dest & 0x100000) as u64) << 36 - 20; + instruction &= ((1u32 << bit_res) - 1) as u64; + instruction |= inst_norm << bit_res; + let mut j_0: size_t = 0; + while j_0 < 6 { + *buffer.offset((i + j_0 + byte_pos) as isize) = + (instruction >> (8 * j_0)) as u8; + j_0 += 1; + } + } + } + slot += 1; + bit_pos += 41; + } + i += 16; + } + i +} +extern "C" fn ia64_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + unsafe { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + ia64_code + as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 16, + 16, + is_encoder, + ) + } +} +pub unsafe extern "C" fn lzma_simple_ia64_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + ia64_coder_init(next, allocator, filters, true) +} +pub unsafe extern "C" fn lzma_simple_ia64_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + ia64_coder_init(next, allocator, filters, false) +} diff --git a/liblzma-rs/src/simple/mod.rs b/liblzma-rs/src/simple/mod.rs new file mode 100644 index 00000000..f3c7f3a8 --- /dev/null +++ b/liblzma-rs/src/simple/mod.rs @@ -0,0 +1,11 @@ +pub mod arm; +pub mod arm64; +pub mod armthumb; +pub mod ia64; +pub mod powerpc; +pub mod riscv; +pub mod simple_coder; +pub mod simple_decoder; +pub mod simple_encoder; +pub mod sparc; +pub mod x86; diff --git a/liblzma-rs/src/simple/powerpc.rs b/liblzma-rs/src/simple/powerpc.rs new file mode 100644 index 00000000..573672b1 --- /dev/null +++ b/liblzma-rs/src/simple/powerpc.rs @@ -0,0 +1,70 @@ +use crate::types::*; +unsafe extern "C" fn powerpc_code( + _simple: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + size &= !(3); + let mut i: size_t = 0; + i = 0; + while i < size { + if *buffer.offset(i as isize) >> 2 == 0x12 && *buffer.offset((i + 3) as isize) & 3 == 1 { + let src: u32 = (*buffer.offset(i as isize) as u32 & 3) << 24 + | (*buffer.offset((i + 1) as isize) as u32) << 16 + | (*buffer.offset((i + 2) as isize) as u32) << 8 + | *buffer.offset((i + 3) as isize) as u32 & !(3); + let mut dest: u32 = 0; + if is_encoder { + dest = now_pos.wrapping_add(i as u32).wrapping_add(src); + } else { + dest = src.wrapping_sub(now_pos.wrapping_add(i as u32)); + } + *buffer.offset(i as isize) = (0x48 | dest >> 24 & 0x3) as u8; + *buffer.offset((i + 1) as isize) = (dest >> 16) as u8; + *buffer.offset((i + 2) as isize) = (dest >> 8) as u8; + *buffer.offset((i + 3) as isize) &= 0x3; + *buffer.offset((i + 3) as isize) = + (*buffer.offset((i + 3) as isize) as u32 | dest) as u8; + } + i += 4; + } + i +} +extern "C" fn powerpc_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + unsafe { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + powerpc_code + as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 4, + 4, + is_encoder, + ) + } +} +pub unsafe extern "C" fn lzma_simple_powerpc_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + powerpc_coder_init(next, allocator, filters, true) +} +pub unsafe extern "C" fn lzma_simple_powerpc_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + powerpc_coder_init(next, allocator, filters, false) +} diff --git a/liblzma-rs/src/simple/riscv.rs b/liblzma-rs/src/simple/riscv.rs new file mode 100644 index 00000000..ccbacc7c --- /dev/null +++ b/liblzma-rs/src/simple/riscv.rs @@ -0,0 +1,214 @@ +use crate::types::*; +#[inline] +extern "C" fn read32be(buf: *const u8) -> u32 { + return unsafe { + let mut num: u32 = (*buf as u32) << 24; + num |= (*buf.offset(1) as u32) << 16; + num |= (*buf.offset(2) as u32) << 8; + num |= *buf.offset(3) as u32; + num + }; +} +#[inline] +extern "C" fn write32be(buf: *mut u8, num: u32) { + unsafe { + *buf = (num >> 24) as u8; + *buf.offset(1) = (num >> 16) as u8; + *buf.offset(2) = (num >> 8) as u8; + *buf.offset(3) = num as u8; + } +} +unsafe extern "C" fn riscv_encode( + _simple: *mut c_void, + now_pos: u32, + _is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + if size < 8 { + return 0; + } + size -= 8; + let mut i: size_t = 0; + let mut current_block_22: u64; + i = 0; + while i <= size { + let mut inst: u32 = *buffer.offset(i as isize) as u32; + if inst == 0xef { + let b1: u32 = *buffer.offset((i + 1) as isize) as u32; + if b1 & 0xd == 0 { + let b2: u32 = *buffer.offset((i + 2) as isize) as u32; + let b3: u32 = *buffer.offset((i + 3) as isize) as u32; + let pc: u32 = now_pos.wrapping_add(i as u32); + let mut addr: u32 = (b1 & 0xf0) << 8 + | (b2 & 0xf) << 16 + | (b2 & 0x10) << 7 + | (b2 & 0xe0) >> 4 + | (b3 & 0x7f) << 4 + | (b3 & 0x80) << 13; + addr = addr.wrapping_add(pc); + *buffer.offset((i + 1) as isize) = (b1 & 0xf | addr >> 13 & 0xf0) as u8; + *buffer.offset((i + 2) as isize) = (addr >> 9) as u8; + *buffer.offset((i + 3) as isize) = (addr >> 1) as u8; + i += 4 - 2; + } + } else if inst & 0x7f == 0x17 { + inst |= (*buffer.offset((i + 1) as isize) as u32) << 8; + inst |= (*buffer.offset((i + 2) as isize) as u32) << 16; + inst |= (*buffer.offset((i + 3) as isize) as u32) << 24; + if inst & 0xe80 != 0 { + let inst2: u32 = read32le(buffer.offset(i as isize).offset(4)); + if (inst << 8 ^ inst2.wrapping_sub(3)) & 0xf8003 != 0 { + i += 6 - 2; + current_block_22 = 12517898123489920830; + } else { + let mut addr_0: u32 = inst & 0xfffff000; + addr_0 = addr_0.wrapping_add((inst2 >> 20).wrapping_sub(inst2 >> 19 & 0x1000)); + addr_0 = addr_0.wrapping_add(now_pos.wrapping_add(i as u32)); + inst = (0x17 | (2) << 7) as u32 | inst2 << 12; + write32le(buffer.offset(i as isize), inst); + write32be(buffer.offset(i as isize).offset(4), addr_0); + current_block_22 = 15125582407903384992; + } + } else { + let fake_rs1: u32 = inst >> 27; + if inst.wrapping_sub(0x3117) << 18 >= fake_rs1 & 0x1d { + i += 4 - 2; + current_block_22 = 12517898123489920830; + } else { + let fake_addr: u32 = read32le(buffer.offset(i as isize).offset(4)) as u32; + let fake_inst2: u32 = inst >> 12 | fake_addr << 20; + inst = 0x17 | fake_rs1 << 7 | fake_addr & 0xfffff000; + write32le(buffer.offset(i as isize), inst); + write32le(buffer.offset(i as isize).offset(4), fake_inst2); + current_block_22 = 15125582407903384992; + } + } + match current_block_22 { + 12517898123489920830 => {} + _ => { + i += 8 - 2; + } + } + } + i += 2; + } + i +} +pub unsafe extern "C" fn lzma_simple_riscv_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + riscv_encode as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 8, + 2, + true, + ) +} +pub unsafe fn lzma_bcj_riscv_encode(mut start_offset: u32, buf: *mut u8, size: size_t) -> size_t { + start_offset = (start_offset & !1u32) as u32; + riscv_encode(core::ptr::null_mut(), start_offset, true, buf, size) +} +unsafe extern "C" fn riscv_decode( + _simple: *mut c_void, + now_pos: u32, + _is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + if size < 8 { + return 0; + } + size -= 8; + let mut i: size_t = 0; + let mut current_block_23: u64; + i = 0; + while i <= size { + let mut inst: u32 = *buffer.offset(i as isize) as u32; + if inst == 0xef { + let b1: u32 = *buffer.offset((i + 1) as isize) as u32; + if b1 & 0xd == 0 { + let b2: u32 = *buffer.offset((i + 2) as isize) as u32; + let b3: u32 = *buffer.offset((i + 3) as isize) as u32; + let pc: u32 = now_pos.wrapping_add(i as u32); + let mut addr: u32 = (b1 & 0xf0) << 13 | b2 << 9 | b3 << 1; + addr = addr.wrapping_sub(pc); + *buffer.offset((i + 1) as isize) = (b1 & 0xf | addr >> 8 & 0xf0) as u8; + *buffer.offset((i + 2) as isize) = + (addr >> 16 & 0xf | addr >> 7 & 0x10 | addr << 4 & 0xe0) as u8; + *buffer.offset((i + 3) as isize) = (addr >> 4 & 0x7f | addr >> 13 & 0x80) as u8; + i += 4 - 2; + } + } else if inst & 0x7f == 0x17 { + let mut inst2: u32 = 0; + inst |= (*buffer.offset((i + 1) as isize) as u32) << 8; + inst |= (*buffer.offset((i + 2) as isize) as u32) << 16; + inst |= (*buffer.offset((i + 3) as isize) as u32) << 24; + if inst & 0xe80 != 0 { + inst2 = read32le(buffer.offset(i as isize).offset(4)); + if (inst << 8 ^ inst2.wrapping_sub(3)) & 0xf8003 != 0 { + i += 6 - 2; + current_block_23 = 12517898123489920830; + } else { + let mut addr_0: u32 = inst & 0xfffff000; + addr_0 = addr_0.wrapping_add(inst2 >> 20); + inst = (0x17 | (2) << 7) as u32 | inst2 << 12; + inst2 = addr_0; + current_block_23 = 6669252993407410313; + } + } else { + let inst2_rs1: u32 = inst >> 27; + if inst.wrapping_sub(0x3117) << 18 >= inst2_rs1 & 0x1d { + i += 4 - 2; + current_block_23 = 12517898123489920830; + } else { + let mut addr_1: u32 = read32be(buffer.offset(i as isize).offset(4)); + addr_1 = addr_1.wrapping_sub(now_pos.wrapping_add(i as u32)); + inst2 = inst >> 12 | addr_1 << 20; + inst = 0x17 | inst2_rs1 << 7 | addr_1.wrapping_add(0x800) & 0xfffff000; + current_block_23 = 6669252993407410313; + } + } + match current_block_23 { + 12517898123489920830 => {} + _ => { + write32le(buffer.offset(i as isize), inst); + write32le(buffer.offset(i as isize).offset(4), inst2); + i += 8 - 2; + } + } + } + i += 2; + } + i +} +pub unsafe extern "C" fn lzma_simple_riscv_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + riscv_decode as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 8, + 2, + false, + ) +} +pub unsafe fn lzma_bcj_riscv_decode(mut start_offset: u32, buf: *mut u8, size: size_t) -> size_t { + start_offset = (start_offset & !1u32) as u32; + riscv_decode(core::ptr::null_mut(), start_offset, false, buf, size) +} diff --git a/liblzma-rs/src/simple/simple_coder.rs b/liblzma-rs/src/simple/simple_coder.rs new file mode 100644 index 00000000..2c8bc11e --- /dev/null +++ b/liblzma-rs/src/simple/simple_coder.rs @@ -0,0 +1,273 @@ +use crate::types::*; +unsafe fn copy_or_code( + coder: *mut lzma_simple_coder, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + if (*coder).next.code.is_none() { + lzma_bufcpy(in_0, in_pos, in_size, out, out_pos, out_size); + if (*coder).is_encoder && action == LZMA_FINISH && *in_pos == in_size { + (*coder).end_was_reached = true; + } + } else { + let ret: lzma_ret = (*coder).next.code.unwrap()( + (*coder).next.coder, + allocator, + in_0, + in_pos, + in_size, + out, + out_pos, + out_size, + action, + ); + if ret == LZMA_STREAM_END { + (*coder).end_was_reached = true; + } else if ret != LZMA_OK { + return ret; + } + } + LZMA_OK +} +unsafe fn call_filter(coder: *mut lzma_simple_coder, buffer: *mut u8, size: size_t) -> size_t { + let filtered: size_t = (*coder).filter.unwrap()( + (*coder).simple, + (*coder).now_pos, + (*coder).is_encoder, + buffer, + size, + ) as size_t; + (*coder).now_pos = (*coder).now_pos.wrapping_add(filtered as u32); + filtered +} +unsafe extern "C" fn simple_code( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + in_0: *const u8, + in_pos: *mut size_t, + in_size: size_t, + out: *mut u8, + out_pos: *mut size_t, + out_size: size_t, + action: lzma_action, +) -> lzma_ret { + let coder: *mut lzma_simple_coder = coder_ptr as *mut lzma_simple_coder; + if action == LZMA_SYNC_FLUSH { + return LZMA_OPTIONS_ERROR; + } + if (*coder).pos < (*coder).filtered { + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + (*coder).filtered, + out, + out_pos, + out_size, + ); + if (*coder).pos < (*coder).filtered { + return LZMA_OK; + } + if (*coder).end_was_reached { + return LZMA_STREAM_END; + } + } + (*coder).filtered = 0; + let out_avail: size_t = out_size - *out_pos; + let buf_avail: size_t = (*coder).size - (*coder).pos; + if out_avail > buf_avail || buf_avail == 0 { + let out_start: size_t = *out_pos; + if buf_avail > 0 { + core::ptr::copy_nonoverlapping( + (::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8) + .offset((*coder).pos as isize) as *const u8, + out.offset(*out_pos as isize) as *mut u8, + buf_avail, + ); + } + *out_pos += buf_avail; + let ret: lzma_ret = copy_or_code( + coder, allocator, in_0, in_pos, in_size, out, out_pos, out_size, action, + ); + if ret != LZMA_OK { + return ret; + } + let size: size_t = *out_pos - out_start; + let filtered: size_t = if size == 0 { + 0 + } else { + call_filter(coder, out.offset(out_start as isize), size) as size_t + }; + let unfiltered: size_t = size - filtered; + (*coder).pos = 0; + (*coder).size = unfiltered; + if (*coder).end_was_reached { + (*coder).size = 0; + } else if unfiltered > 0 { + *out_pos -= unfiltered; + core::ptr::copy_nonoverlapping( + out.offset(*out_pos as isize) as *const u8, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + unfiltered, + ); + } + } else if (*coder).pos > 0 { + core::ptr::copy( + (::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8).offset((*coder).pos as isize) + as *const u8, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + buf_avail, + ); + (*coder).size -= (*coder).pos; + (*coder).pos = 0; + } + if (*coder).size > 0 { + let ret_0: lzma_ret = copy_or_code( + coder, + allocator, + in_0, + in_pos, + in_size, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).size), + (*coder).allocated, + action, + ); + if ret_0 != LZMA_OK { + return ret_0; + } + (*coder).filtered = call_filter( + coder, + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + (*coder).size, + ); + if (*coder).end_was_reached { + (*coder).filtered = (*coder).size; + } + lzma_bufcpy( + ::core::ptr::addr_of_mut!((*coder).buffer) as *mut u8, + ::core::ptr::addr_of_mut!((*coder).pos), + (*coder).filtered, + out, + out_pos, + out_size, + ); + } + if (*coder).end_was_reached && (*coder).pos == (*coder).size { + return LZMA_STREAM_END; + } + LZMA_OK +} +unsafe extern "C" fn simple_coder_end(coder_ptr: *mut c_void, allocator: *const lzma_allocator) { + let coder: *mut lzma_simple_coder = coder_ptr as *mut lzma_simple_coder; + lzma_next_end(::core::ptr::addr_of_mut!((*coder).next), allocator); + crate::alloc::internal_free((*coder).simple, allocator); + crate::alloc::internal_free(coder as *mut c_void, allocator); +} +unsafe extern "C" fn simple_coder_update( + coder_ptr: *mut c_void, + allocator: *const lzma_allocator, + _filters_null: *const lzma_filter, + reversed_filters: *const lzma_filter, +) -> lzma_ret { + let coder: *mut lzma_simple_coder = coder_ptr as *mut lzma_simple_coder; + lzma_next_filter_update( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + reversed_filters.offset(1), + ) +} +pub unsafe fn lzma_simple_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + filter: Option size_t>, + simple_size: size_t, + unfiltered_max: size_t, + alignment: u32, + is_encoder: bool, +) -> lzma_ret { + let mut coder: *mut lzma_simple_coder = (*next).coder as *mut lzma_simple_coder; + if coder.is_null() { + coder = crate::alloc::internal_alloc_bytes( + core::mem::size_of::() + 2 * unfiltered_max, + allocator, + ) as *mut lzma_simple_coder; + if coder.is_null() { + return LZMA_MEM_ERROR; + } + (*next).coder = coder as *mut c_void; + (*next).code = Some( + simple_code + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, + ); + (*next).end = Some( + simple_coder_end as unsafe extern "C" fn(*mut c_void, *const lzma_allocator) -> (), + ); + (*next).update = Some( + simple_coder_update + as unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + ); + (*coder).next = lzma_next_coder_s { + coder: core::ptr::null_mut(), + id: LZMA_VLI_UNKNOWN, + init: 0, + code: None, + end: None, + get_progress: None, + get_check: None, + memconfig: None, + update: None, + set_out_limit: None, + }; + (*coder).filter = filter; + (*coder).allocated = 2 * unfiltered_max; + if simple_size > 0 { + (*coder).simple = crate::alloc::internal_alloc_bytes(simple_size, allocator); + if (*coder).simple.is_null() { + return LZMA_MEM_ERROR; + } + } else { + (*coder).simple = core::ptr::null_mut(); + } + } + if !(*filters).options.is_null() { + let simple: *const lzma_options_bcj = (*filters).options as *const lzma_options_bcj; + (*coder).now_pos = (*simple).start_offset; + if (*coder).now_pos & (alignment - 1) != 0 { + return LZMA_OPTIONS_ERROR; + } + } else { + (*coder).now_pos = 0; + } + (*coder).is_encoder = is_encoder; + (*coder).end_was_reached = false; + (*coder).pos = 0; + (*coder).filtered = 0; + (*coder).size = 0; + lzma_next_filter_init( + ::core::ptr::addr_of_mut!((*coder).next), + allocator, + filters.offset(1), + ) +} diff --git a/liblzma-rs/src/simple/simple_decoder.rs b/liblzma-rs/src/simple/simple_decoder.rs new file mode 100644 index 00000000..006ab061 --- /dev/null +++ b/liblzma-rs/src/simple/simple_decoder.rs @@ -0,0 +1,26 @@ +use crate::types::*; +pub unsafe extern "C" fn lzma_simple_props_decode( + options: *mut *mut c_void, + allocator: *const lzma_allocator, + props: *const u8, + props_size: size_t, +) -> lzma_ret { + if props_size == 0 { + return LZMA_OK; + } + if props_size != 4 { + return LZMA_OPTIONS_ERROR; + } + let opt: *mut lzma_options_bcj = + lzma_alloc(core::mem::size_of::(), allocator) as *mut lzma_options_bcj; + if opt.is_null() { + return LZMA_MEM_ERROR; + } + (*opt).start_offset = read32le(props); + if (*opt).start_offset == 0 { + lzma_free(opt as *mut c_void, allocator); + } else { + *options = opt as *mut c_void; + } + LZMA_OK +} diff --git a/liblzma-rs/src/simple/simple_encoder.rs b/liblzma-rs/src/simple/simple_encoder.rs new file mode 100644 index 00000000..4aca0cb1 --- /dev/null +++ b/liblzma-rs/src/simple/simple_encoder.rs @@ -0,0 +1,24 @@ +use crate::types::*; +pub unsafe extern "C" fn lzma_simple_props_size( + size: *mut u32, + options: *const c_void, +) -> lzma_ret { + let opt: *const lzma_options_bcj = options as *const lzma_options_bcj; + *size = (if opt.is_null() || (*opt).start_offset == 0 { + 0 + } else { + 4 + }) as u32; + LZMA_OK +} +pub unsafe extern "C" fn lzma_simple_props_encode( + options: *const c_void, + out: *mut u8, +) -> lzma_ret { + let opt: *const lzma_options_bcj = options as *const lzma_options_bcj; + if opt.is_null() || (*opt).start_offset == 0 { + return LZMA_OK; + } + write32le(out, (*opt).start_offset); + LZMA_OK +} diff --git a/liblzma-rs/src/simple/sparc.rs b/liblzma-rs/src/simple/sparc.rs new file mode 100644 index 00000000..84be333a --- /dev/null +++ b/liblzma-rs/src/simple/sparc.rs @@ -0,0 +1,74 @@ +use crate::types::*; +unsafe extern "C" fn sparc_code( + _simple: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + mut size: size_t, +) -> size_t { + size &= !(3); + let mut i: size_t = 0; + i = 0; + while i < size { + if *buffer.offset(i as isize) == 0x40 && *buffer.offset((i + 1) as isize) & 0xc0 == 0 + || *buffer.offset(i as isize) == 0x7f && *buffer.offset((i + 1) as isize) & 0xc0 == 0xc0 + { + let mut src: u32 = (*buffer.offset(i as isize) as u32) << 24 + | (*buffer.offset((i + 1) as isize) as u32) << 16 + | (*buffer.offset((i + 2) as isize) as u32) << 8 + | *buffer.offset((i + 3) as isize) as u32; + src <<= 2; + let mut dest: u32 = 0; + if is_encoder { + dest = now_pos.wrapping_add(i as u32).wrapping_add(src); + } else { + dest = src.wrapping_sub(now_pos.wrapping_add(i as u32)); + } + dest >>= 2; + dest = + 0u32.wrapping_sub(dest >> 22 & 1) << 22 & 0x3fffffff | dest & 0x3fffff | 0x40000000; + *buffer.offset(i as isize) = (dest >> 24) as u8; + *buffer.offset((i + 1) as isize) = (dest >> 16) as u8; + *buffer.offset((i + 2) as isize) = (dest >> 8) as u8; + *buffer.offset((i + 3) as isize) = dest as u8; + } + i += 4; + } + i +} +extern "C" fn sparc_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + unsafe { + lzma_simple_coder_init( + next, + allocator, + filters, + Some( + sparc_code + as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + 0, + 4, + 4, + is_encoder, + ) + } +} +pub unsafe extern "C" fn lzma_simple_sparc_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + sparc_coder_init(next, allocator, filters, true) +} +pub unsafe extern "C" fn lzma_simple_sparc_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + sparc_coder_init(next, allocator, filters, false) +} diff --git a/liblzma-rs/src/simple/x86.rs b/liblzma-rs/src/simple/x86.rs new file mode 100644 index 00000000..41bca8a3 --- /dev/null +++ b/liblzma-rs/src/simple/x86.rs @@ -0,0 +1,158 @@ +use crate::types::*; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_simple_x86 { + pub prev_mask: u32, + pub prev_pos: u32, +} +unsafe extern "C" fn x86_code( + simple_ptr: *mut c_void, + now_pos: u32, + is_encoder: bool, + buffer: *mut u8, + size: size_t, +) -> size_t { + static mut MASK_TO_BIT_NUMBER: [u32; 5] = [0, 1, 2, 2, 3]; + let simple: *mut lzma_simple_x86 = simple_ptr as *mut lzma_simple_x86; + let mut prev_mask: u32 = (*simple).prev_mask; + let mut prev_pos: u32 = (*simple).prev_pos; + if size < 5 { + return 0; + } + if now_pos.wrapping_sub(prev_pos) > 5 { + prev_pos = now_pos.wrapping_sub(5); + } + let limit: size_t = size - 5; + let mut buffer_pos: size_t = 0; + while buffer_pos <= limit { + let mut b: u8 = *buffer.offset(buffer_pos as isize); + if b != 0xe8 && b != 0xe9 { + buffer_pos += 1; + } else { + let offset: u32 = now_pos + .wrapping_add(buffer_pos as u32) + .wrapping_sub(prev_pos); + prev_pos = now_pos.wrapping_add(buffer_pos as u32); + if offset > 5 { + prev_mask = 0; + } else { + let mut i: u32 = 0; + while i < offset { + prev_mask &= 0x77; + prev_mask <<= 1; + i += 1; + } + } + b = *buffer.offset((buffer_pos + 4) as isize); + if (b == 0 || b == 0xff) && prev_mask >> 1 <= 4 && prev_mask >> 1 != 3 { + let mut src: u32 = (b as u32) << 24 + | (*buffer.offset((buffer_pos + 3) as isize) as u32) << 16 + | (*buffer.offset((buffer_pos + 2) as isize) as u32) << 8 + | *buffer.offset((buffer_pos + 1) as isize) as u32; + let mut dest: u32 = 0; + loop { + if is_encoder { + dest = src + .wrapping_add(now_pos.wrapping_add(buffer_pos as u32).wrapping_add(5)); + } else { + dest = src + .wrapping_sub(now_pos.wrapping_add(buffer_pos as u32).wrapping_add(5)); + } + if prev_mask == 0 { + break; + } + let i_0: u32 = MASK_TO_BIT_NUMBER[(prev_mask >> 1) as usize]; + b = (dest >> (24u32).wrapping_sub(i_0.wrapping_mul(8))) as u8; + if b != 0 && b != 0xff { + break; + } + src = + dest ^ (1u32 << (32u32).wrapping_sub(i_0.wrapping_mul(8))).wrapping_sub(1); + } + *buffer.offset((buffer_pos + 4) as isize) = !(dest >> 24 & 1).wrapping_sub(1) as u8; + *buffer.offset((buffer_pos + 3) as isize) = (dest >> 16) as u8; + *buffer.offset((buffer_pos + 2) as isize) = (dest >> 8) as u8; + *buffer.offset((buffer_pos + 1) as isize) = dest as u8; + buffer_pos += 5; + prev_mask = 0; + } else { + buffer_pos += 1; + prev_mask |= 1; + if b == 0 || b == 0xff { + prev_mask |= 0x10; + } + } + } + } + (*simple).prev_mask = prev_mask; + (*simple).prev_pos = prev_pos; + buffer_pos +} +extern "C" fn x86_coder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, + is_encoder: bool, +) -> lzma_ret { + return unsafe { + let ret: lzma_ret = lzma_simple_coder_init( + next, + allocator, + filters, + Some( + x86_code as unsafe extern "C" fn(*mut c_void, u32, bool, *mut u8, size_t) -> size_t, + ), + core::mem::size_of::(), + 5, + 1, + is_encoder, + ); + if ret == LZMA_OK { + let coder: *mut lzma_simple_coder = (*next).coder as *mut lzma_simple_coder; + let simple: *mut lzma_simple_x86 = (*coder).simple as *mut lzma_simple_x86; + (*simple).prev_mask = 0; + (*simple).prev_pos = (-5_i32) as u32; + } + ret + }; +} +pub unsafe extern "C" fn lzma_simple_x86_encoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + x86_coder_init(next, allocator, filters, true) +} +pub unsafe fn lzma_bcj_x86_encode(start_offset: u32, buf: *mut u8, size: size_t) -> size_t { + let mut simple: lzma_simple_x86 = lzma_simple_x86 { + prev_mask: 0, + prev_pos: (-5_i32) as u32, + }; + x86_code( + ::core::ptr::addr_of_mut!(simple) as *mut c_void, + start_offset, + true, + buf, + size, + ) +} +pub unsafe extern "C" fn lzma_simple_x86_decoder_init( + next: *mut lzma_next_coder, + allocator: *const lzma_allocator, + filters: *const lzma_filter_info, +) -> lzma_ret { + x86_coder_init(next, allocator, filters, false) +} +pub unsafe fn lzma_bcj_x86_decode(start_offset: u32, buf: *mut u8, size: size_t) -> size_t { + let mut simple: lzma_simple_x86 = lzma_simple_x86 { + prev_mask: 0, + prev_pos: (-5_i32) as u32, + }; + x86_code( + ::core::ptr::addr_of_mut!(simple) as *mut c_void, + start_offset, + false, + buf, + size, + ) +} diff --git a/liblzma-rs/src/tuklib/mod.rs b/liblzma-rs/src/tuklib/mod.rs new file mode 100644 index 00000000..fadc9769 --- /dev/null +++ b/liblzma-rs/src/tuklib/mod.rs @@ -0,0 +1,2 @@ +pub mod tuklib_cpucores; +pub mod tuklib_physmem; diff --git a/liblzma-rs/src/tuklib/tuklib_cpucores.rs b/liblzma-rs/src/tuklib/tuklib_cpucores.rs new file mode 100644 index 00000000..b0db2196 --- /dev/null +++ b/liblzma-rs/src/tuklib/tuklib_cpucores.rs @@ -0,0 +1,6 @@ +pub fn tuklib_cpucores() -> u32 { + match std::thread::available_parallelism() { + Ok(n) => n.get() as u32, + Err(_) => 0, + } +} diff --git a/liblzma-rs/src/tuklib/tuklib_physmem.rs b/liblzma-rs/src/tuklib/tuklib_physmem.rs new file mode 100644 index 00000000..587fa05a --- /dev/null +++ b/liblzma-rs/src/tuklib/tuklib_physmem.rs @@ -0,0 +1,39 @@ +pub fn tuklib_physmem() -> u64 { + #[cfg(target_os = "macos")] + { + let mut memsize: u64 = 0; + let mut len = core::mem::size_of::() as libc::size_t; + let mut mib: [libc::c_int; 2] = [libc::CTL_HW, libc::HW_MEMSIZE]; + if unsafe { + libc::sysctl( + mib.as_mut_ptr(), + 2, + &mut memsize as *mut u64 as *mut libc::c_void, + &mut len, + core::ptr::null_mut(), + 0, + ) + } == 0 + { + return memsize; + } + 0 + } + #[cfg(target_os = "linux")] + { + let pages = unsafe { libc::sysconf(libc::_SC_PHYS_PAGES) }; + let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) }; + if pages > 0 && page_size > 0 { + return (pages as u64).wrapping_mul(page_size as u64); + } + 0 + } + #[cfg(target_os = "windows")] + { + 0 + } + #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] + { + 0 + } +} diff --git a/liblzma-rs/src/types.rs b/liblzma-rs/src/types.rs new file mode 100644 index 00000000..dd2b6f13 --- /dev/null +++ b/liblzma-rs/src/types.rs @@ -0,0 +1,1186 @@ +pub use std::os::raw::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_ulonglong, c_void}; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +pub type size_t = usize; +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +pub type size_t = libc::size_t; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +pub type uintptr_t = usize; +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +pub type uintptr_t = libc::uintptr_t; +pub type lzma_bool = c_uchar; +pub type lzma_ret = c_uint; +pub type lzma_action = c_uint; +pub type lzma_check = c_uint; +pub type lzma_vli = u64; +pub type lzma_reserved_enum = c_uint; +pub type lzma_mode = c_uint; +pub type lzma_match_finder = c_uint; +pub type lzma_lzma_state = c_uint; +pub type lzma_delta_type = c_uint; +pub type probability = u16; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_allocator { + pub alloc: Option *mut c_void>, + pub free: Option ()>, + pub opaque: *mut c_void, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_filter { + pub id: lzma_vli, + pub options: *mut c_void, +} +pub type lzma_end_function = Option ()>; +pub type lzma_code_function = Option< + unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const u8, + *mut size_t, + size_t, + *mut u8, + *mut size_t, + size_t, + lzma_action, + ) -> lzma_ret, +>; +pub type lzma_next_coder = lzma_next_coder_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_next_coder_s { + pub coder: *mut c_void, + pub id: lzma_vli, + pub init: uintptr_t, + pub code: lzma_code_function, + pub end: lzma_end_function, + pub get_progress: Option ()>, + pub get_check: Option lzma_check>, + pub memconfig: Option lzma_ret>, + pub update: Option< + unsafe extern "C" fn( + *mut c_void, + *const lzma_allocator, + *const lzma_filter, + *const lzma_filter, + ) -> lzma_ret, + >, + pub set_out_limit: Option lzma_ret>, +} +pub type lzma_init_function = Option< + unsafe extern "C" fn( + *mut lzma_next_coder, + *const lzma_allocator, + *const lzma_filter_info, + ) -> lzma_ret, +>; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_filter_info_s { + pub id: lzma_vli, + pub init: lzma_init_function, + pub options: *mut c_void, +} +pub type lzma_filter_info = lzma_filter_info_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_options_lzma { + pub dict_size: u32, + pub preset_dict: *const u8, + pub preset_dict_size: u32, + pub lc: u32, + pub lp: u32, + pub pb: u32, + pub mode: lzma_mode, + pub nice_len: u32, + pub mf: lzma_match_finder, + pub depth: u32, + pub ext_flags: u32, + pub ext_size_low: u32, + pub ext_size_high: u32, + pub reserved_int4: u32, + pub reserved_int5: u32, + pub reserved_int6: u32, + pub reserved_int7: u32, + pub reserved_int8: u32, + pub reserved_enum1: lzma_reserved_enum, + pub reserved_enum2: lzma_reserved_enum, + pub reserved_enum3: lzma_reserved_enum, + pub reserved_enum4: lzma_reserved_enum, + pub reserved_ptr1: *mut c_void, + pub reserved_ptr2: *mut c_void, +} +pub type lzma_internal_sequence = c_uint; +pub const ISEQ_RUN: lzma_internal_sequence = 0; +pub const ISEQ_SYNC_FLUSH: lzma_internal_sequence = 1; +pub const ISEQ_FULL_FLUSH: lzma_internal_sequence = 2; +pub const ISEQ_FINISH: lzma_internal_sequence = 3; +pub const ISEQ_FULL_BARRIER: lzma_internal_sequence = 4; +pub const ISEQ_END: lzma_internal_sequence = 5; +pub const ISEQ_ERROR: lzma_internal_sequence = 6; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_internal_s { + pub next: lzma_next_coder, + pub sequence: lzma_internal_sequence, + pub avail_in: size_t, + pub supported_actions: [bool; 5], + pub allow_buf_error: bool, +} +pub type lzma_internal = lzma_internal_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_stream { + pub next_in: *const u8, + pub avail_in: size_t, + pub total_in: u64, + pub next_out: *mut u8, + pub avail_out: size_t, + pub total_out: u64, + pub allocator: *const lzma_allocator, + pub internal: *mut lzma_internal, + pub reserved_ptr1: *mut c_void, + pub reserved_ptr2: *mut c_void, + pub reserved_ptr3: *mut c_void, + pub reserved_ptr4: *mut c_void, + pub seek_pos: u64, + pub reserved_int2: u64, + pub reserved_int3: size_t, + pub reserved_int4: size_t, + pub reserved_enum1: lzma_reserved_enum, + pub reserved_enum2: lzma_reserved_enum, +} +pub const LZMA_OK: lzma_ret = 0; +pub const LZMA_STREAM_END: lzma_ret = 1; +pub const LZMA_NO_CHECK: lzma_ret = 2; +pub const LZMA_UNSUPPORTED_CHECK: lzma_ret = 3; +pub const LZMA_GET_CHECK: lzma_ret = 4; +pub const LZMA_MEM_ERROR: lzma_ret = 5; +pub const LZMA_MEMLIMIT_ERROR: lzma_ret = 6; +pub const LZMA_FORMAT_ERROR: lzma_ret = 7; +pub const LZMA_OPTIONS_ERROR: lzma_ret = 8; +pub const LZMA_DATA_ERROR: lzma_ret = 9; +pub const LZMA_BUF_ERROR: lzma_ret = 10; +pub const LZMA_PROG_ERROR: lzma_ret = 11; +pub const LZMA_SEEK_NEEDED: lzma_ret = 12; +pub const LZMA_RET_INTERNAL1: lzma_ret = 101; +pub const LZMA_RET_INTERNAL2: lzma_ret = 102; +pub const LZMA_RET_INTERNAL3: lzma_ret = 103; +pub const LZMA_RET_INTERNAL4: lzma_ret = 104; +pub const LZMA_RET_INTERNAL5: lzma_ret = 105; +pub const LZMA_RET_INTERNAL6: lzma_ret = 106; +pub const LZMA_RET_INTERNAL7: lzma_ret = 107; +pub const LZMA_RET_INTERNAL8: lzma_ret = 108; +pub const LZMA_RUN: lzma_action = 0; +pub const LZMA_SYNC_FLUSH: lzma_action = 1; +pub const LZMA_FULL_FLUSH: lzma_action = 2; +pub const LZMA_FINISH: lzma_action = 3; +pub const LZMA_FULL_BARRIER: lzma_action = 4; +pub const LZMA_CHECK_NONE: lzma_check = 0; +pub const LZMA_CHECK_CRC32: lzma_check = 1; +pub const LZMA_CHECK_CRC64: lzma_check = 4; +pub const LZMA_CHECK_SHA256: lzma_check = 10; +pub const LZMA_RESERVED_ENUM: lzma_reserved_enum = 0; +pub const UINT32_MAX: c_uint = u32::MAX; +pub const UINT64_MAX: u64 = u64::MAX; +pub const LZMA_VLI_MAX: lzma_vli = u64::MAX / 2; +pub const LZMA_VLI_UNKNOWN: lzma_vli = u64::MAX; +pub const LZMA_MF_HC3: lzma_match_finder = 3; +pub const LZMA_MF_HC4: lzma_match_finder = 4; +pub const LZMA_MF_BT2: lzma_match_finder = 18; +pub const LZMA_MF_BT3: lzma_match_finder = 19; +pub const LZMA_MF_BT4: lzma_match_finder = 20; +pub const LZMA_MODE_FAST: lzma_mode = 1; +pub const LZMA_MODE_NORMAL: lzma_mode = 2; +pub const LZMA_CHECK_ID_MAX: lzma_check = 15; +pub const LZMA_DELTA_TYPE_BYTE: lzma_delta_type = 0; +pub const LZMA_FILTER_DELTA: lzma_vli = 0x3; +pub const LZMA_FILTER_X86: lzma_vli = 0x4; +pub const LZMA_FILTER_POWERPC: lzma_vli = 0x5; +pub const LZMA_FILTER_IA64: lzma_vli = 0x6; +pub const LZMA_FILTER_ARM: lzma_vli = 0x7; +pub const LZMA_FILTER_ARMTHUMB: lzma_vli = 0x8; +pub const LZMA_FILTER_SPARC: lzma_vli = 0x9; +pub const LZMA_FILTER_ARM64: lzma_vli = 0xa; +pub const LZMA_FILTER_RISCV: lzma_vli = 0xb; +pub const LZMA_FILTER_LZMA1: lzma_vli = 0x4000000000000001; +pub const LZMA_FILTER_LZMA1EXT: lzma_vli = 0x4000000000000002; +pub const LZMA_FILTER_LZMA2: lzma_vli = 0x21; +pub const LZMA_FILTER_RESERVED_START: lzma_vli = 1 << 62; +pub const LZMA_TELL_NO_CHECK: c_uint = 0x1; +pub const LZMA_TELL_UNSUPPORTED_CHECK: c_uint = 0x2; +pub const LZMA_TELL_ANY_CHECK: c_uint = 0x4; +pub const LZMA_CONCATENATED: c_uint = 0x8; +pub const LZMA_IGNORE_CHECK: c_uint = 0x10; +pub const LZMA_FAIL_FAST: c_uint = 0x20; +pub const LZMA_STREAM_HEADER_SIZE: u32 = 12; +pub const LZMA_BLOCK_HEADER_SIZE_MAX: u32 = 1024; +pub const LZMA_MEMUSAGE_BASE: u64 = 1 << 15; +pub const LZMA_DICT_SIZE_MIN: c_uint = 4096; +pub const STATE_LIT_LIT: lzma_lzma_state = 0; +pub const STATE_MATCH_LIT_LIT: lzma_lzma_state = 1; +pub const STATE_REP_LIT_LIT: lzma_lzma_state = 2; +pub const STATE_SHORTREP_LIT_LIT: lzma_lzma_state = 3; +pub const STATE_MATCH_LIT: lzma_lzma_state = 4; +pub const STATE_REP_LIT: lzma_lzma_state = 5; +pub const STATE_SHORTREP_LIT: lzma_lzma_state = 6; +pub const STATE_LIT_MATCH: lzma_lzma_state = 7; +pub const STATE_LIT_LONGREP: lzma_lzma_state = 8; +pub const STATE_LIT_SHORTREP: lzma_lzma_state = 9; +pub const STATE_NONLIT_MATCH: lzma_lzma_state = 10; +pub const STATE_NONLIT_REP: lzma_lzma_state = 11; +pub const LZMA_VLI_BYTES_MAX: u32 = 9; +pub const LZMA_FILTERS_MAX: u32 = 4; +pub const LZMA_LCLP_MAX: u32 = 4; +pub const LZMA_PB_MAX: u32 = 4; +pub const LZMA_DELTA_DIST_MAX: u32 = 256; +pub const LZMA_BACKWARD_SIZE_MIN: u32 = 4; +pub const LZMA_BACKWARD_SIZE_MAX: u64 = 1 << 34; +pub const LZMA_SUPPORTED_FLAGS: c_uint = LZMA_TELL_NO_CHECK + | LZMA_TELL_UNSUPPORTED_CHECK + | LZMA_TELL_ANY_CHECK + | LZMA_IGNORE_CHECK + | LZMA_CONCATENATED + | LZMA_FAIL_FAST; +pub const UINTPTR_MAX: c_ulong = uintptr_t::MAX as c_ulong; +pub const SIZE_MAX: c_ulong = UINTPTR_MAX; +pub const INDEX_INDICATOR: u8 = 0; +pub const UNPADDED_SIZE_MIN: c_ulonglong = 5; +pub const UNPADDED_SIZE_MAX: c_ulonglong = LZMA_VLI_MAX & !3; +pub const LZMA_THREADS_MAX: u32 = 16384; +pub const LZMA_DELTA_DIST_MIN: u32 = 1; +pub const LZMA_LZMA1EXT_ALLOW_EOPM: c_uint = 0x1; +pub const RC_BIT_MODEL_TOTAL_BITS: u32 = 11; +pub const RC_BIT_MODEL_TOTAL: c_uint = 1u32 << RC_BIT_MODEL_TOTAL_BITS; +pub const MATCH_LEN_MIN: u32 = 2; +pub const REPS: u32 = 4; +pub const LIT_STATES: u32 = 7; +pub const FASTPOS_BITS: u32 = 13; +pub const OPTS: u32 = 1 << 12; +pub const LZ_DICT_REPEAT_MAX: u32 = 288; +pub const LZ_DICT_INIT_POS: u32 = 2 * LZ_DICT_REPEAT_MAX; +pub const ALIGN_BITS: u32 = 4; +pub const ALIGN_SIZE: u32 = 1 << ALIGN_BITS; +pub const ALIGN_MASK: u32 = ALIGN_SIZE - 1; +pub const DIST_STATES: u32 = 4; +pub const DIST_SLOT_BITS: u32 = 6; +pub const DIST_MODEL_START: u32 = 4; +pub const DIST_MODEL_END: u32 = 14; +pub const FULL_DISTANCES_BITS: u32 = DIST_MODEL_END / 2; +pub const FULL_DISTANCES: u32 = 1 << FULL_DISTANCES_BITS; +pub const STATES: u32 = 12; +pub const LITERAL_CODER_SIZE: c_uint = 0x300; +pub const LEN_LOW_BITS: u32 = 3; +pub const LEN_LOW_SYMBOLS: u32 = 1 << LEN_LOW_BITS; +pub const LEN_MID_BITS: u32 = 3; +pub const LEN_MID_SYMBOLS: u32 = 1 << LEN_MID_BITS; +pub const LEN_HIGH_BITS: u32 = 8; +pub const LEN_HIGH_SYMBOLS: u32 = 1 << LEN_HIGH_BITS; +pub const RC_MOVE_BITS: u32 = 5; +pub const RC_SHIFT_BITS: u32 = 8; +pub const RC_TOP_BITS: u32 = 24; +pub const RC_TOP_VALUE: c_uint = 1u32 << RC_TOP_BITS; +pub const RC_MOVE_REDUCING_BITS: u32 = 4; +pub const LZMA2_CHUNK_MAX: c_uint = 1u32 << 16; +pub const LZMA2_HEADER_UNCOMPRESSED: u32 = 3; +pub const HASH_2_SIZE: c_uint = 1u32 << 10; +pub const HASH_3_SIZE: c_uint = 1u32 << 16; +pub const LZMA_CHECK_SIZE_MAX: u32 = 64; +pub const LZMA_STREAM_FLAGS_SIZE: u32 = 2; +pub const LZMA_PRESET_EXTREME: c_uint = 1u32 << 31; +pub const COMPRESSED_SIZE_MAX: c_ulonglong = LZMA_VLI_MAX + .wrapping_sub(LZMA_BLOCK_HEADER_SIZE_MAX as u64) + .wrapping_sub(LZMA_CHECK_SIZE_MAX as u64); +pub const MYTHREAD_RET_VALUE: *mut c_void = core::ptr::null_mut(); +pub const SIG_SETMASK: c_int = 3; +pub type worker_state = c_uint; +pub type lzma_index_iter_mode = c_uint; +pub const THR_IDLE: worker_state = 0; +pub const THR_RUN: worker_state = 1; +pub const LZMA_INDEX_ITER_ANY: lzma_index_iter_mode = 0; +pub const LZMA_INDEX_ITER_STREAM: lzma_index_iter_mode = 1; +pub const LZMA_INDEX_ITER_BLOCK: lzma_index_iter_mode = 2; +pub const LZMA_INDEX_ITER_NONEMPTY_BLOCK: lzma_index_iter_mode = 3; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_iter { + pub stream: lzma_index_iter_stream, + pub block: lzma_index_iter_block, + pub internal: [lzma_index_iter_internal; 6], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union lzma_index_iter_internal { + pub p: *const c_void, + pub s: size_t, + pub v: lzma_vli, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_iter_block { + pub number_in_file: lzma_vli, + pub compressed_file_offset: lzma_vli, + pub uncompressed_file_offset: lzma_vli, + pub number_in_stream: lzma_vli, + pub compressed_stream_offset: lzma_vli, + pub uncompressed_stream_offset: lzma_vli, + pub uncompressed_size: lzma_vli, + pub unpadded_size: lzma_vli, + pub total_size: lzma_vli, + pub reserved_vli1: lzma_vli, + pub reserved_vli2: lzma_vli, + pub reserved_vli3: lzma_vli, + pub reserved_vli4: lzma_vli, + pub reserved_ptr1: *const c_void, + pub reserved_ptr2: *const c_void, + pub reserved_ptr3: *const c_void, + pub reserved_ptr4: *const c_void, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_index_iter_stream { + pub flags: *const lzma_stream_flags, + pub reserved_ptr1: *const c_void, + pub reserved_ptr2: *const c_void, + pub reserved_ptr3: *const c_void, + pub number: lzma_vli, + pub block_count: lzma_vli, + pub compressed_offset: lzma_vli, + pub uncompressed_offset: lzma_vli, + pub compressed_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub padding: lzma_vli, + pub reserved_vli1: lzma_vli, + pub reserved_vli2: lzma_vli, + pub reserved_vli3: lzma_vli, + pub reserved_vli4: lzma_vli, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_block { + pub version: u32, + pub header_size: u32, + pub check: lzma_check, + pub compressed_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub filters: *mut lzma_filter, + pub raw_check: [u8; 64], + pub reserved_ptr1: *mut c_void, + pub reserved_ptr2: *mut c_void, + pub reserved_ptr3: *mut c_void, + pub reserved_int1: u32, + pub reserved_int2: u32, + pub reserved_int3: lzma_vli, + pub reserved_int4: lzma_vli, + pub reserved_int5: lzma_vli, + pub reserved_int6: lzma_vli, + pub reserved_int7: lzma_vli, + pub reserved_int8: lzma_vli, + pub reserved_enum1: lzma_reserved_enum, + pub reserved_enum2: lzma_reserved_enum, + pub reserved_enum3: lzma_reserved_enum, + pub reserved_enum4: lzma_reserved_enum, + pub ignore_check: lzma_bool, + pub reserved_bool2: lzma_bool, + pub reserved_bool3: lzma_bool, + pub reserved_bool4: lzma_bool, + pub reserved_bool5: lzma_bool, + pub reserved_bool6: lzma_bool, + pub reserved_bool7: lzma_bool, + pub reserved_bool8: lzma_bool, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_stream_flags { + pub version: u32, + pub backward_size: lzma_vli, + pub check: lzma_check, + pub reserved_enum1: lzma_reserved_enum, + pub reserved_enum2: lzma_reserved_enum, + pub reserved_enum3: lzma_reserved_enum, + pub reserved_enum4: lzma_reserved_enum, + pub reserved_bool1: lzma_bool, + pub reserved_bool2: lzma_bool, + pub reserved_bool3: lzma_bool, + pub reserved_bool4: lzma_bool, + pub reserved_bool5: lzma_bool, + pub reserved_bool6: lzma_bool, + pub reserved_bool7: lzma_bool, + pub reserved_bool8: lzma_bool, + pub reserved_int1: u32, + pub reserved_int2: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_sha256_state { + pub state: [u32; 8], + pub size: u64, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union lzma_check_state_buffer { + pub u8_0: [u8; 64], + pub u32_0: [u32; 16], + pub u64_0: [u64; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union lzma_check_state_inner { + pub crc32: u32, + pub crc64: u64, + pub sha256: lzma_sha256_state, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_check_state { + pub buffer: lzma_check_state_buffer, + pub state: lzma_check_state_inner, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_options_delta { + pub type_0: lzma_delta_type, + pub dist: u32, + pub reserved_int1: u32, + pub reserved_int2: u32, + pub reserved_int3: u32, + pub reserved_int4: u32, + pub reserved_ptr1: *mut c_void, + pub reserved_ptr2: *mut c_void, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_options_easy { + pub filters: [lzma_filter; 5], + pub opt_lzma: lzma_options_lzma, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_dict { + pub buf: *mut u8, + pub pos: size_t, + pub full: size_t, + pub limit: size_t, + pub size: size_t, + pub has_wrapped: bool, + pub need_reset: bool, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lz_decoder { + pub coder: *mut c_void, + pub code: Option< + unsafe extern "C" fn( + *mut c_void, + *mut lzma_dict, + *const u8, + *mut size_t, + size_t, + ) -> lzma_ret, + >, + pub reset: Option ()>, + pub set_uncompressed: Option ()>, + pub end: Option ()>, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_match { + pub len: u32, + pub dist: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_mf_s { + pub buffer: *mut u8, + pub size: u32, + pub keep_size_before: u32, + pub keep_size_after: u32, + pub offset: u32, + pub read_pos: u32, + pub read_ahead: u32, + pub read_limit: u32, + pub write_pos: u32, + pub pending: u32, + pub find: Option u32>, + pub skip: Option ()>, + pub hash: *mut u32, + pub son: *mut u32, + pub cyclic_pos: u32, + pub cyclic_size: u32, + pub hash_mask: u32, + pub depth: u32, + pub nice_len: u32, + pub match_len_max: u32, + pub action: lzma_action, + pub hash_count: u32, + pub sons_count: u32, +} +pub type lzma_mf = lzma_mf_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_delta_coder { + pub next: lzma_next_coder, + pub distance: size_t, + pub pos: u8, + pub history: [u8; LZMA_DELTA_DIST_MAX as usize], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lz_encoder { + pub coder: *mut c_void, + pub code: Option< + unsafe extern "C" fn(*mut c_void, *mut lzma_mf, *mut u8, *mut size_t, size_t) -> lzma_ret, + >, + pub end: Option ()>, + pub options_update: Option lzma_ret>, + pub set_out_limit: Option lzma_ret>, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_outbuf_s { + pub next: *mut lzma_outbuf, + pub worker: *mut c_void, + pub allocated: size_t, + pub pos: size_t, + pub decoder_in_pos: size_t, + pub finished: bool, + pub finish_ret: lzma_ret, + pub unpadded_size: lzma_vli, + pub uncompressed_size: lzma_vli, + pub buf: [u8; 0], +} +pub type lzma_outbuf = lzma_outbuf_s; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_outq { + pub head: *mut lzma_outbuf, + pub tail: *mut lzma_outbuf, + pub read_pos: size_t, + pub cache: *mut lzma_outbuf, + pub mem_allocated: u64, + pub mem_in_use: u64, + pub bufs_in_use: u32, + pub bufs_allocated: u32, + pub bufs_limit: u32, +} +pub use crate::common::index::{lzma_index, lzma_index_s}; +pub use crate::common::index_hash::{lzma_index_hash, lzma_index_hash_s}; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_lzma1_encoder_s { + pub rc: lzma_range_encoder, + pub uncomp_size: u64, + pub out_limit: u64, + pub uncomp_size_ptr: *mut u64, + pub state: lzma_lzma_state, + pub reps: [u32; 4], + pub matches: [lzma_match; 274], + pub matches_count: u32, + pub longest_match_length: u32, + pub fast_mode: bool, + pub is_initialized: bool, + pub is_flushed: bool, + pub use_eopm: bool, + pub pos_mask: u32, + pub literal_context_bits: u32, + pub literal_mask: u32, + pub literal: [probability; 12288], + pub is_match: [[probability; 16]; 12], + pub is_rep: [probability; 12], + pub is_rep0: [probability; 12], + pub is_rep1: [probability; 12], + pub is_rep2: [probability; 12], + pub is_rep0_long: [[probability; 16]; 12], + pub dist_slot: [[probability; 64]; 4], + pub dist_special: [probability; 114], + pub dist_align: [probability; 16], + pub match_len_encoder: lzma_length_encoder, + pub rep_len_encoder: lzma_length_encoder, + pub dist_slot_prices: [[u32; 64]; 4], + pub dist_prices: [[u32; 128]; 4], + pub dist_table_size: u32, + pub match_price_count: u32, + pub align_prices: [u32; 16], + pub align_price_count: u32, + pub opts_end_index: u32, + pub opts_current_index: u32, + pub opts: [lzma_optimal; OPTS as usize], +} +pub type lzma_lzma1_encoder = lzma_lzma1_encoder_s; +#[inline] +pub fn read32le(buf: *const u8) -> u32 { + return unsafe { + let mut num: u32 = *buf as u32; + num |= (*buf.offset(1) as u32) << 8; + num |= (*buf.offset(2) as u32) << 16; + num |= (*buf.offset(3) as u32) << 24; + num + }; +} +#[inline] +pub fn write32le(buf: *mut u8, num: u32) { + unsafe { + *buf = num as u8; + *buf.offset(1) = (num >> 8) as u8; + *buf.offset(2) = (num >> 16) as u8; + *buf.offset(3) = (num >> 24) as u8; + } +} +pub type __uint32_t = u32; +pub type __darwin_time_t = c_long; +pub type __darwin_sigset_t = __uint32_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct __darwin_pthread_handler_rec { + pub __routine: Option ()>, + pub __arg: *mut c_void, + pub __next: *mut __darwin_pthread_handler_rec, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_attr_t { + pub __sig: c_long, + pub __opaque: [c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_cond_t { + pub __sig: c_long, + pub __opaque: [c_char; 40], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_condattr_t { + pub __sig: c_long, + pub __opaque: [c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutex_t { + pub __sig: c_long, + pub __opaque: [c_char; 56], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_mutexattr_t { + pub __sig: c_long, + pub __opaque: [c_char; 8], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _opaque_pthread_t { + pub __sig: c_long, + pub __cleanup_stack: *mut __darwin_pthread_handler_rec, + pub __opaque: [c_char; 8176], +} +pub type __darwin_pthread_attr_t = _opaque_pthread_attr_t; +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; +pub type __darwin_pthread_t = *mut _opaque_pthread_t; +pub type pthread_attr_t = __darwin_pthread_attr_t; +pub type sigset_t = __darwin_sigset_t; +pub type time_t = __darwin_time_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct timespec { + pub tv_sec: __darwin_time_t, + pub tv_nsec: c_long, +} +pub type clockid_t = c_uint; +pub const _CLOCK_THREAD_CPUTIME_ID: clockid_t = 16; +pub const _CLOCK_PROCESS_CPUTIME_ID: clockid_t = 12; +pub const _CLOCK_UPTIME_RAW_APPROX: clockid_t = 9; +pub const _CLOCK_UPTIME_RAW: clockid_t = 8; +pub const _CLOCK_MONOTONIC_RAW_APPROX: clockid_t = 5; +pub const _CLOCK_MONOTONIC_RAW: clockid_t = 4; +pub const _CLOCK_MONOTONIC: clockid_t = 6; +pub const _CLOCK_REALTIME: clockid_t = 0; +pub type pthread_cond_t = __darwin_pthread_cond_t; +pub type pthread_condattr_t = __darwin_pthread_condattr_t; +pub type pthread_mutex_t = __darwin_pthread_mutex_t; +pub type pthread_mutexattr_t = __darwin_pthread_mutexattr_t; +pub type pthread_t = __darwin_pthread_t; +pub type mythread = pthread_t; +pub type mythread_mutex = pthread_mutex_t; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct mythread_cond { + pub cond: pthread_cond_t, + pub clk_id: clockid_t, +} +pub type mythread_condtime = timespec; +#[inline] +pub fn mythread_sigmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) { + let _ret: c_int = + unsafe { pthread_sigmask(how, set as *const sigset_t, oset as *mut sigset_t) }; +} +#[inline] +pub fn mythread_create( + thread: *mut mythread, + func: Option *mut c_void>, + arg: *mut c_void, +) -> c_int { + let mut old: sigset_t = 0; + let mut all: sigset_t = 0; + all = !(0 as sigset_t); + mythread_sigmask( + SIG_SETMASK, + ::core::ptr::addr_of_mut!(all), + ::core::ptr::addr_of_mut!(old), + ); + let ret: c_int = unsafe { + pthread_create( + thread as *mut pthread_t, + core::ptr::null(), + func as Option *mut c_void>, + arg as *mut c_void, + ) + }; + mythread_sigmask( + SIG_SETMASK, + ::core::ptr::addr_of_mut!(old), + core::ptr::null_mut(), + ); + ret +} +#[inline] +pub fn mythread_join(thread: mythread) -> c_int { + unsafe { pthread_join(thread as pthread_t, core::ptr::null_mut()) } +} +#[inline] +pub fn mythread_mutex_init(mutex: *mut mythread_mutex) -> c_int { + unsafe { pthread_mutex_init(mutex as *mut pthread_mutex_t, core::ptr::null()) } +} +#[inline] +pub fn mythread_mutex_destroy(mutex: *mut mythread_mutex) { + let _ret: c_int = unsafe { pthread_mutex_destroy(mutex as *mut pthread_mutex_t) }; +} +#[inline] +pub fn mythread_mutex_lock(mutex: *mut mythread_mutex) { + let _ret: c_int = unsafe { pthread_mutex_lock(mutex as *mut pthread_mutex_t) }; +} +#[inline] +pub fn mythread_mutex_unlock(mutex: *mut mythread_mutex) { + let _ret: c_int = unsafe { pthread_mutex_unlock(mutex as *mut pthread_mutex_t) }; +} +#[inline] +pub fn mythread_cond_init(mycond: *mut mythread_cond) -> c_int { + return unsafe { + (*mycond).clk_id = _CLOCK_REALTIME; + pthread_cond_init(::core::ptr::addr_of_mut!((*mycond).cond), core::ptr::null()) + }; +} +#[inline] +pub fn mythread_cond_destroy(cond: *mut mythread_cond) { + let _ret: c_int = unsafe { pthread_cond_destroy(::core::ptr::addr_of_mut!((*cond).cond)) }; +} +#[inline] +pub fn mythread_cond_signal(cond: *mut mythread_cond) { + let _ret: c_int = unsafe { pthread_cond_signal(::core::ptr::addr_of_mut!((*cond).cond)) }; +} +#[inline] +pub fn mythread_cond_wait(cond: *mut mythread_cond, mutex: *mut mythread_mutex) { + let _ret: c_int = unsafe { + pthread_cond_wait( + ::core::ptr::addr_of_mut!((*cond).cond), + mutex as *mut pthread_mutex_t, + ) + }; +} +#[inline] +pub fn mythread_cond_timedwait( + cond: *mut mythread_cond, + mutex: *mut mythread_mutex, + condtime: *const mythread_condtime, +) -> c_int { + let ret: c_int = unsafe { + pthread_cond_timedwait( + ::core::ptr::addr_of_mut!((*cond).cond), + mutex as *mut pthread_mutex_t, + condtime as *const timespec, + ) + }; + ret +} +#[inline] +pub fn mythread_condtime_set( + condtime: *mut mythread_condtime, + cond: *const mythread_cond, + timeout_ms: u32, +) { + unsafe { + (*condtime).tv_sec = timeout_ms.wrapping_div(1000) as time_t as __darwin_time_t; + (*condtime).tv_nsec = timeout_ms.wrapping_rem(1000).wrapping_mul(1_000_000) as c_long; + let mut now: timespec = timespec { + tv_sec: 0, + tv_nsec: 0, + }; + let _ret: c_int = clock_gettime((*cond).clk_id, ::core::ptr::addr_of_mut!(now)); + (*condtime).tv_sec += now.tv_sec; + (*condtime).tv_nsec += now.tv_nsec; + if (*condtime).tv_nsec >= 1_000_000_000 { + (*condtime).tv_nsec -= 1_000_000_000; + (*condtime).tv_sec += 1; + } + } +} +#[inline] +pub fn vli_ceil4(vli: lzma_vli) -> lzma_vli { + vli.wrapping_add(3) & !(3) +} +#[inline] +pub fn index_size_unpadded(count: lzma_vli, index_list_size: lzma_vli) -> lzma_vli { + (1u32.wrapping_add(lzma_vli_size(count)) as lzma_vli) + .wrapping_add(index_list_size) + .wrapping_add(4) +} +#[inline] +pub fn lzma_outq_has_buf(outq: *const lzma_outq) -> bool { + unsafe { (*outq).bufs_in_use < (*outq).bufs_limit } +} +#[inline] +pub fn lzma_outq_is_empty(outq: *const lzma_outq) -> bool { + unsafe { (*outq).bufs_in_use == 0 } +} +#[inline] +pub unsafe fn mf_ptr(mf: *const lzma_mf) -> *const u8 { + (*mf).buffer.offset((*mf).read_pos as isize) +} +#[inline] +pub unsafe fn mf_avail(mf: *const lzma_mf) -> u32 { + (*mf).write_pos.wrapping_sub((*mf).read_pos) +} +#[inline] +pub unsafe fn mf_skip(mf: *mut lzma_mf, amount: u32) { + mf_skip_raw(mf, amount, (*mf).skip.unwrap()); +} + +#[inline(always)] +pub unsafe fn mf_skip_raw( + mf: *mut lzma_mf, + amount: u32, + skip: unsafe extern "C" fn(*mut lzma_mf, u32) -> (), +) { + if amount != 0 { + skip(mf, amount); + (*mf).read_ahead = (*mf).read_ahead.wrapping_add(amount); + } +} +#[inline(always)] +pub unsafe fn lzma_memcmplen(buf1: *const u8, buf2: *const u8, mut len: u32, limit: u32) -> u32 { + debug_assert!(len <= limit); + debug_assert!(limit <= u32::MAX / 2); + + #[cfg(all( + target_endian = "little", + any(target_arch = "aarch64", target_arch = "x86_64") + ))] + { + while len < limit { + let lhs = core::ptr::read_unaligned(buf1.add(len as usize) as *const u64); + let rhs = core::ptr::read_unaligned(buf2.add(len as usize) as *const u64); + let diff = lhs.wrapping_sub(rhs); + if diff != 0 { + return core::cmp::min(len + (diff.trailing_zeros() >> 3), limit); + } + len += 8; + } + limit + } + + #[cfg(not(all( + target_endian = "little", + any(target_arch = "aarch64", target_arch = "x86_64") + )))] + while len < limit && *buf1.offset(len as isize) == *buf2.offset(len as isize) { + len += 1; + } + + #[cfg(not(all( + target_endian = "little", + any(target_arch = "aarch64", target_arch = "x86_64") + )))] + { + len + } +} +#[inline] +pub unsafe fn get_dist_slot(dist: u32) -> u32 { + if dist < 1 << FASTPOS_BITS + (0 + 0 * (FASTPOS_BITS - 1)) { + return lzma_fastpos[dist as usize] as u32; + } + if dist < 1 << FASTPOS_BITS + (0 + 1 * (FASTPOS_BITS - 1)) { + return (lzma_fastpos[(dist >> 0 + 1 * (FASTPOS_BITS - 1)) as usize] as u32) + .wrapping_add((2 * (0 + 1 * (FASTPOS_BITS - 1))) as u32); + } + (lzma_fastpos[(dist >> 0 + 2 * (FASTPOS_BITS - 1)) as usize] as u32) + .wrapping_add((2 * (0 + 2 * (FASTPOS_BITS - 1))) as u32) +} +#[inline] +unsafe fn rc_price_at(index: u32) -> u32 { + debug_assert!((index as usize) < 128); + *(::core::ptr::addr_of!(lzma_rc_prices) as *const u8).add(index as usize) as u32 +} +#[inline] +pub fn rc_bit_price(prob: probability, bit: u32) -> u32 { + unsafe { + rc_price_at( + ((prob as u32 ^ 0u32.wrapping_sub(bit) & (RC_BIT_MODEL_TOTAL as u32).wrapping_sub(1)) + >> RC_MOVE_REDUCING_BITS) as u32, + ) + } +} +#[inline] +pub fn rc_bit_0_price(prob: probability) -> u32 { + unsafe { rc_price_at((prob >> RC_MOVE_REDUCING_BITS) as u32) } +} +#[inline] +pub fn rc_bit_1_price(prob: probability) -> u32 { + unsafe { + rc_price_at( + ((prob as u32 ^ RC_BIT_MODEL_TOTAL.wrapping_sub(1)) >> RC_MOVE_REDUCING_BITS) as u32, + ) + } +} +#[inline] +pub unsafe fn rc_bittree_price(probs: *const probability, bit_levels: u32, mut symbol: u32) -> u32 { + let mut price: u32 = 0; + symbol = (symbol as u32).wrapping_add(1u32 << bit_levels) as u32; + loop { + let bit: u32 = symbol & 1; + symbol >>= 1; + price = price.wrapping_add(rc_bit_price(*probs.offset(symbol as isize), bit)); + if symbol == 1 { + break; + } + } + price +} +#[inline] +pub fn mf_get_hash_bytes(match_finder: lzma_match_finder) -> u32 { + match_finder as u32 & 0xf +} +#[inline] +pub unsafe fn is_lclppb_valid(options: *const lzma_options_lzma) -> bool { + (*options).lc <= LZMA_LCLP_MAX + && (*options).lp <= LZMA_LCLP_MAX + && (*options).lc.wrapping_add((*options).lp) <= LZMA_LCLP_MAX + && (*options).pb <= LZMA_PB_MAX +} +#[inline] +pub unsafe fn literal_init(probs: *mut probability, lc: u32, lp: u32) { + let coders: size_t = (LITERAL_CODER_SIZE << lc.wrapping_add(lp)) as size_t; + let mut i: size_t = 0; + while i < coders { + *probs.offset(i as isize) = (RC_BIT_MODEL_TOTAL >> 1) as probability; + i += 1; + } +} +pub fn is_backward_size_valid(options: *const lzma_stream_flags) -> bool { + unsafe { + (*options).backward_size >= LZMA_BACKWARD_SIZE_MIN as lzma_vli + && (*options).backward_size <= LZMA_BACKWARD_SIZE_MAX + && (*options).backward_size & 3 == 0 + } +} +#[inline] +pub fn index_size(count: lzma_vli, index_list_size: lzma_vli) -> lzma_vli { + vli_ceil4(index_size_unpadded(count, index_list_size)) +} +pub fn lzma_outq_outbuf_memusage(buf_size: size_t) -> u64 { + (core::mem::size_of::()).wrapping_add(buf_size as usize) as u64 +} +#[inline] +pub unsafe fn aligned_read32ne(buf: *const u8) -> u32 { + *(buf as *const u32) +} +pub type rc_symbol = c_uint; +pub const RC_FLUSH: rc_symbol = 4; +pub const RC_DIRECT_1: rc_symbol = 3; +pub const RC_DIRECT_0: rc_symbol = 2; +pub const RC_BIT_1: rc_symbol = 1; +pub const RC_BIT_0: rc_symbol = 0; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_range_encoder { + pub low: u64, + pub cache_size: u64, + pub range: u32, + pub cache: u8, + pub out_total: u64, + pub count: size_t, + pub pos: size_t, + pub symbols: [rc_symbol; 53], + pub probs: [*mut probability; 53], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_optimal { + pub state: lzma_lzma_state, + pub prev_1_is_literal: bool, + pub prev_2: bool, + pub pos_prev_2: u32, + pub back_prev_2: u32, + pub price: u32, + pub pos_prev: u32, + pub back_prev: u32, + pub backs: [u32; 4], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_length_encoder { + pub choice: probability, + pub choice2: probability, + pub low: [[probability; 8]; 16], + pub mid: [[probability; 8]; 16], + pub high: [probability; 256], + pub prices: [[u32; 272]; 16], + pub table_size: u32, + pub counters: [u32; 16], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_options_bcj { + pub start_offset: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_mt { + pub flags: u32, + pub threads: u32, + pub block_size: u64, + pub timeout: u32, + pub preset: u32, + pub filters: *const lzma_filter, + pub check: lzma_check, + pub reserved_enum1: lzma_reserved_enum, + pub reserved_enum2: lzma_reserved_enum, + pub reserved_enum3: lzma_reserved_enum, + pub reserved_int1: u32, + pub reserved_int2: u32, + pub reserved_int3: u32, + pub reserved_int4: u32, + pub memlimit_threading: u64, + pub memlimit_stop: u64, + pub reserved_int7: u64, + pub reserved_int8: u64, + pub reserved_ptr1: *mut c_void, + pub reserved_ptr2: *mut c_void, + pub reserved_ptr3: *mut c_void, + pub reserved_ptr4: *mut c_void, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_filter_coder { + pub id: lzma_vli, + pub init: lzma_init_function, + pub memusage: Option u64>, +} +pub type lzma_filter_find = Option *const lzma_filter_coder>; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct lzma_simple_coder { + pub next: lzma_next_coder, + pub end_was_reached: bool, + pub is_encoder: bool, + pub filter: Option size_t>, + pub simple: *mut c_void, + pub now_pos: u32, + pub allocated: size_t, + pub pos: size_t, + pub filtered: size_t, + pub size: size_t, + pub buffer: [u8; 0], +} +pub use crate::check::check::{ + lzma_check_finish, lzma_check_init, lzma_check_is_supported, lzma_check_size, lzma_check_update, +}; +pub use crate::check::crc32_fast::lzma_crc32; +pub use crate::common::block_decoder::lzma_block_decoder_init; +pub use crate::common::block_encoder::lzma_block_encoder_init; +pub use crate::common::block_header_decoder::lzma_block_header_decode; +pub use crate::common::block_header_encoder::{lzma_block_header_encode, lzma_block_header_size}; +pub use crate::common::block_util::lzma_block_unpadded_size; +pub use crate::common::common::{ + lzma_alloc, lzma_alloc_zero, lzma_bufcpy, lzma_end, lzma_free, lzma_next_end, + lzma_next_filter_init, lzma_next_filter_update, lzma_strm_init, +}; +pub use crate::common::easy_preset::lzma_easy_preset; +pub use crate::common::filter_common::{ + lzma_filters_copy, lzma_filters_free, lzma_raw_coder_init, lzma_raw_coder_memusage, +}; +pub use crate::common::filter_decoder::{lzma_raw_decoder_init, lzma_raw_decoder_memusage}; +pub use crate::common::filter_encoder::{lzma_raw_encoder_init, lzma_raw_encoder_memusage}; +pub use crate::common::index::{ + lzma_index_append, lzma_index_end, lzma_index_init, lzma_index_memusage, + lzma_index_padding_size, lzma_index_size, +}; +pub use crate::common::index_encoder::lzma_index_encoder_init; +pub use crate::common::index_hash::{ + lzma_index_hash_append, lzma_index_hash_decode, lzma_index_hash_end, lzma_index_hash_init, + lzma_index_hash_size, +}; +pub use crate::common::outqueue::{ + lzma_outq_end, lzma_outq_get_buf, lzma_outq_init, lzma_outq_is_readable, + lzma_outq_prealloc_buf, lzma_outq_read, +}; +pub use crate::common::stream_decoder::lzma_stream_decoder_init; +pub use crate::common::stream_flags_common::lzma_stream_flags_compare; +pub use crate::common::stream_flags_decoder::{ + lzma_stream_footer_decode, lzma_stream_header_decode, +}; +pub use crate::common::stream_flags_encoder::{ + lzma_stream_footer_encode, lzma_stream_header_encode, +}; +pub use crate::common::vli_decoder::lzma_vli_decode; +pub use crate::common::vli_encoder::lzma_vli_encode; +pub use crate::common::vli_size::lzma_vli_size; +pub use crate::delta::delta_common::{lzma_delta_coder_init, lzma_delta_coder_memusage}; +pub use crate::lz::lz_encoder_mf::{lzma_mf_find, lzma_mf_find_raw}; +pub use crate::lzma::fastpos_table::lzma_fastpos; +pub use crate::lzma::lzma_decoder::{ + lzma_lzma_decoder_init, lzma_lzma_decoder_memusage_nocheck, lzma_lzma_lclppb_decode, +}; +pub use crate::lzma::lzma_encoder::{ + lzma_lzma_encoder_init, lzma_lzma_encoder_memusage, lzma_lzma_lclppb_encode, +}; +pub use crate::lzma::lzma_encoder_presets::lzma_lzma_preset; +pub use crate::rangecoder::price_table::lzma_rc_prices; +pub use crate::simple::simple_coder::lzma_simple_coder_init; +extern "C" { + pub fn clock_gettime(__clock_id: clockid_t, __tp: *mut timespec) -> c_int; + pub fn pthread_cond_destroy(_: *mut pthread_cond_t) -> c_int; + pub fn pthread_cond_init(_: *mut pthread_cond_t, _: *const pthread_condattr_t) -> c_int; + pub fn pthread_cond_signal(_: *mut pthread_cond_t) -> c_int; + pub fn pthread_cond_timedwait( + _: *mut pthread_cond_t, + _: *mut pthread_mutex_t, + _: *const timespec, + ) -> c_int; + pub fn pthread_cond_wait(_: *mut pthread_cond_t, _: *mut pthread_mutex_t) -> c_int; + pub fn pthread_create( + _: *mut pthread_t, + _: *const pthread_attr_t, + _: Option *mut c_void>, + _: *mut c_void, + ) -> c_int; + pub fn pthread_join(_: pthread_t, _: *mut *mut c_void) -> c_int; + pub fn pthread_mutex_destroy(_: *mut pthread_mutex_t) -> c_int; + pub fn pthread_mutex_init(_: *mut pthread_mutex_t, _: *const pthread_mutexattr_t) -> c_int; + pub fn pthread_mutex_lock(_: *mut pthread_mutex_t) -> c_int; + pub fn pthread_mutex_unlock(_: *mut pthread_mutex_t) -> c_int; + pub fn pthread_sigmask(_: c_int, _: *const sigset_t, _: *mut sigset_t) -> c_int; + pub fn memcmp(s1: *const c_void, s2: *const c_void, n: size_t) -> c_int; + pub fn strlen(s: *const c_char) -> size_t; +} + +pub unsafe fn memchr(s: *const c_void, c: c_int, n: size_t) -> *mut c_void { + let bytes = core::slice::from_raw_parts(s as *const u8, n); + let needle = c as u8; + match ::memchr::memchr(needle, bytes) { + Some(index) => (s as *const u8).add(index) as *mut c_void, + None => core::ptr::null_mut(), + } +} diff --git a/liblzma-sys/Cargo.toml b/liblzma-sys/Cargo.toml index 3adf733c..de0881a0 100644 --- a/liblzma-sys/Cargo.toml +++ b/liblzma-sys/Cargo.toml @@ -17,7 +17,7 @@ High level Rust bindings are available in the `liblzma` crate. """ categories = ["external-ffi-bindings"] edition = "2021" -rust-version = "1.60" +rust-version = "1.63" exclude = ["xz/.github/", "xz/tests/files/*"] [dependencies] diff --git a/src/lib.rs b/src/lib.rs index d08daba9..994a4845 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,14 @@ #![doc(html_root_url = "https://docs.rs/liblzma/0.4.6")] #![deny(missing_docs)] +#[cfg(not(any(feature = "rust-backend", feature = "c-backend")))] +compile_error!("Either `rust-backend` or `c-backend` feature must be enabled"); + +// When c-backend is active (without rust-backend), alias liblzma_c_sys +// so that internal `liblzma_sys::` references resolve to the C library. +#[cfg(all(feature = "c-backend", not(feature = "rust-backend")))] +extern crate liblzma_c_sys as liblzma_sys; + use std::io::{self, prelude::*}; pub mod stream; @@ -103,7 +111,7 @@ pub fn copy_decode(source: R, mut destination: W) -> io::Resu } /// Find the size in bytes of uncompressed data from xz file. -#[cfg(feature = "bindgen")] +#[cfg(any(feature = "rust-backend", feature = "bindgen"))] pub fn uncompressed_size(mut source: R) -> io::Result { use std::mem::MaybeUninit; let mut footer = [0u8; liblzma_sys::LZMA_STREAM_HEADER_SIZE as usize]; @@ -171,13 +179,13 @@ pub fn uncompressed_size(mut source: R) -> io::Result { Ok(uncompressed_size) } -#[cfg(test)] +#[cfg(all(test, not(target_family = "wasm")))] mod tests { use super::*; + #[cfg(not(target_family = "wasm"))] use quickcheck::quickcheck; - #[cfg(all(target_family = "wasm", target_os = "unknown"))] - use wasm_bindgen_test::wasm_bindgen_test as test; + #[cfg(not(target_family = "wasm"))] #[test] fn all() { quickcheck(test as fn(_) -> _); @@ -189,6 +197,7 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[test] fn copy() { quickcheck(test as fn(_) -> _); @@ -202,8 +211,9 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[test] - #[cfg(feature = "bindgen")] + #[cfg(any(feature = "rust-backend", feature = "bindgen"))] fn size() { quickcheck(test as fn(_) -> _); diff --git a/src/read.rs b/src/read.rs index cea37de8..d550db0d 100644 --- a/src/read.rs +++ b/src/read.rs @@ -226,7 +226,10 @@ impl Write for XzDecoder { #[cfg(test)] mod tests { use super::*; - use crate::stream::{LzmaOptions, PRESET_EXTREME}; + #[cfg(not(target_family = "wasm"))] + use crate::stream::LzmaOptions; + use crate::stream::PRESET_EXTREME; + #[cfg(not(target_family = "wasm"))] use quickcheck::quickcheck; use rand::{thread_rng, Rng}; use std::iter; @@ -326,6 +329,7 @@ mod tests { assert_eq!(data, m); } + #[cfg(not(target_family = "wasm"))] #[test] fn qc_lzma1() { quickcheck(test as fn(_) -> _); @@ -341,6 +345,7 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[test] fn qc() { quickcheck(test as fn(_) -> _); @@ -354,6 +359,7 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[cfg(feature = "parallel")] #[test] fn qc_parallel_encode() { @@ -379,6 +385,7 @@ mod tests { assert_eq!(data, m); } + #[cfg(not(target_family = "wasm"))] #[cfg(feature = "parallel")] #[test] fn qc_parallel_decode() { diff --git a/src/write.rs b/src/write.rs index cb438255..ae24fab5 100644 --- a/src/write.rs +++ b/src/write.rs @@ -382,7 +382,10 @@ impl Drop for XzDecoder { #[cfg(test)] mod tests { use super::*; - use crate::stream::{LzmaOptions, PRESET_EXTREME}; + #[cfg(not(target_family = "wasm"))] + use crate::stream::LzmaOptions; + use crate::stream::PRESET_EXTREME; + #[cfg(not(target_family = "wasm"))] use quickcheck::quickcheck; use std::iter::repeat; #[cfg(all(target_family = "wasm", target_os = "unknown"))] @@ -420,6 +423,7 @@ mod tests { assert_eq!(data, input); } + #[cfg(not(target_family = "wasm"))] #[test] fn qc_lzma1() { quickcheck(test as fn(_) -> _); @@ -435,6 +439,7 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[test] fn qc() { quickcheck(test as fn(_) -> _); @@ -447,6 +452,7 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[cfg(feature = "parallel")] #[test] fn qc_parallel_encode() { @@ -460,6 +466,7 @@ mod tests { } } + #[cfg(not(target_family = "wasm"))] #[cfg(feature = "parallel")] #[test] fn qc_parallel_decode() { diff --git a/systest/Cargo.toml b/systest/Cargo.toml index 4da58c2e..6c2b8724 100644 --- a/systest/Cargo.toml +++ b/systest/Cargo.toml @@ -7,11 +7,15 @@ edition = "2021" publish = false [dependencies] -liblzma-sys = { path = "../liblzma-sys" } +liblzma-c-sys = { package = "liblzma-sys", path = "../liblzma-sys", optional = true } +liblzma-rs-sys = { path = "../liblzma-rs-sys", optional = true } libc = "0.2" [build-dependencies] ctest2 = "0.4" [features] -bindgen = ["liblzma-sys/bindgen"] +default = ["c-sys"] +c-sys = ["liblzma-c-sys"] +rs-sys = ["liblzma-rs-sys"] +bindgen = ["c-sys", "liblzma-c-sys/bindgen"] diff --git a/systest/build.rs b/systest/build.rs index 9539fdc4..736a65d4 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -1,14 +1,32 @@ use std::env; fn main() { + let use_c_sys = env::var_os("CARGO_FEATURE_C_SYS").is_some(); + let use_rs_sys = env::var_os("CARGO_FEATURE_RS_SYS").is_some(); + match (use_c_sys, use_rs_sys) { + (true, false) | (false, true) => {} + _ => panic!("Enable exactly one of features: c-sys or rs-sys"), + } + let mut cfg = ctest2::TestGenerator::new(); - if let Ok(out) = env::var("DEP_LZMA_INCLUDE") { - cfg.include(&out); + if use_c_sys { + if let Ok(out) = env::var("DEP_LZMA_INCLUDE") { + cfg.include(&out); + } + } else { + // Reuse vendored upstream headers to verify C header compatibility. + cfg.include("../liblzma-sys/xz/src/liblzma/api"); } cfg.header("lzma.h"); cfg.type_name(|n, _s, _| n.to_string()); cfg.define("LZMA_API_STATIC", None); cfg.skip_type(|n| n == "__enum_ty"); - cfg.generate("../liblzma-sys/src/lib.rs", "all.rs"); + + let rust_api = if use_c_sys { + "../liblzma-sys/src/lib.rs" + } else { + "../liblzma-rs-sys/src/lib.rs" + }; + cfg.generate(rust_api, "all.rs"); } diff --git a/systest/src/main.rs b/systest/src/main.rs index ce7f47c8..81b91f5d 100644 --- a/systest/src/main.rs +++ b/systest/src/main.rs @@ -1,4 +1,13 @@ #![allow(bad_style)] -use liblzma_sys::*; + +#[cfg(all(feature = "c-sys", feature = "rs-sys"))] +compile_error!("Enable exactly one backend feature: c-sys or rs-sys"); +#[cfg(not(any(feature = "c-sys", feature = "rs-sys")))] +compile_error!("Enable one backend feature: c-sys or rs-sys"); + +#[cfg(feature = "c-sys")] +use liblzma_c_sys::*; +#[cfg(feature = "rs-sys")] +use liblzma_rs_sys::*; include!(concat!(env!("OUT_DIR"), "/all.rs")); diff --git a/tests/sys_equivalence.rs b/tests/sys_equivalence.rs new file mode 100644 index 00000000..9c92e038 --- /dev/null +++ b/tests/sys_equivalence.rs @@ -0,0 +1,604 @@ +#![cfg(all( + not(target_family = "wasm"), + feature = "rust-backend", + feature = "c-backend" +))] + +use std::collections::BTreeMap; +use std::fs; +use std::path::Path; +use std::ptr; + +use liblzma_c_sys as c_sys; +use liblzma_sys as rs_sys; + +fn parse_feature_table(cargo_toml: &str) -> BTreeMap> { + let mut in_features = false; + let mut features = BTreeMap::new(); + + for raw_line in cargo_toml.lines() { + let line = raw_line.trim(); + if line.starts_with('[') && line.ends_with(']') { + in_features = line == "[features]"; + continue; + } + if !in_features || line.is_empty() || line.starts_with('#') { + continue; + } + + let line = line.split('#').next().unwrap_or("").trim(); + if line.is_empty() { + continue; + } + + let (name, rhs) = line + .split_once('=') + .expect("feature entry must contain '='"); + let name = name.trim().to_owned(); + let rhs = rhs.trim(); + let mut deps = Vec::new(); + + if rhs != "[]" { + assert!( + rhs.starts_with('[') && rhs.ends_with(']'), + "feature value must be an array: {name} = {rhs}", + ); + let inner = &rhs[1..rhs.len() - 1]; + for item in inner.split(',') { + let item = item.trim(); + if item.is_empty() { + continue; + } + let item = item + .strip_prefix('"') + .and_then(|s| s.strip_suffix('"')) + .unwrap_or_else(|| panic!("feature dependency must be quoted: {item}")); + deps.push(item.to_owned()); + } + } + + features.insert(name, deps); + } + + features +} + +#[test] +fn rs_sys_avoids_literal_lzma_const_defs() { + let src = include_str!("../liblzma-rs-sys/src/lib.rs"); + let mut stmt = String::new(); + let mut start_line = 0usize; + let mut in_const = false; + + for (idx, line) in src.lines().enumerate() { + let trimmed = line.trim_start(); + if !in_const && trimmed.starts_with("pub const LZMA_") { + in_const = true; + start_line = idx + 1; + stmt.clear(); + } + + if in_const { + stmt.push_str(trimmed); + stmt.push(' '); + if trimmed.ends_with(';') { + assert!( + stmt.contains("= liblzma_rs::"), + "LZMA const must alias liblzma_rs symbol, not use local literal (line {}): {}", + start_line, + stmt + ); + in_const = false; + } + } + } +} + +#[test] +fn rs_sys_uses_libc_size_t() { + let src = include_str!("../liblzma-rs-sys/src/lib.rs"); + assert!( + src.contains("use libc::size_t;"), + "liblzma-rs-sys must import libc::size_t directly" + ); + assert!( + !src.contains("type size_t ="), + "local size_t alias is forbidden; use libc::size_t" + ); +} + +#[test] +fn cargo_features_match_c_backend() { + let c_sys_features = parse_feature_table(include_str!("../liblzma-sys/Cargo.toml")); + let rs_sys_features = parse_feature_table(include_str!("../liblzma-rs-sys/Cargo.toml")); + + assert_eq!( + rs_sys_features, c_sys_features, + "liblzma-rs-sys feature table must stay compatible with liblzma-sys", + ); +} + +#[test] +fn api_constants_match_c_backend() { + macro_rules! assert_const_eq { + ($($name:ident),+ $(,)?) => { + $( + assert_eq!( + rs_sys::$name as u128, + c_sys::$name as u128, + "constant mismatch: {}", + stringify!($name) + ); + )+ + }; + } + + assert_const_eq!( + LZMA_OK, + LZMA_STREAM_END, + LZMA_NO_CHECK, + LZMA_UNSUPPORTED_CHECK, + LZMA_GET_CHECK, + LZMA_MEM_ERROR, + LZMA_MEMLIMIT_ERROR, + LZMA_FORMAT_ERROR, + LZMA_OPTIONS_ERROR, + LZMA_DATA_ERROR, + LZMA_BUF_ERROR, + LZMA_PROG_ERROR, + LZMA_SEEK_NEEDED, + LZMA_RUN, + LZMA_SYNC_FLUSH, + LZMA_FULL_FLUSH, + LZMA_FULL_BARRIER, + LZMA_FINISH, + LZMA_CHECK_NONE, + LZMA_CHECK_CRC32, + LZMA_CHECK_CRC64, + LZMA_CHECK_SHA256, + LZMA_MODE_FAST, + LZMA_MODE_NORMAL, + LZMA_MF_HC3, + LZMA_MF_HC4, + LZMA_MF_BT2, + LZMA_MF_BT3, + LZMA_MF_BT4, + LZMA_TELL_NO_CHECK, + LZMA_TELL_UNSUPPORTED_CHECK, + LZMA_TELL_ANY_CHECK, + LZMA_IGNORE_CHECK, + LZMA_CONCATENATED, + LZMA_PRESET_DEFAULT, + LZMA_PRESET_LEVEL_MASK, + LZMA_PRESET_EXTREME, + LZMA_DICT_SIZE_MIN, + LZMA_DICT_SIZE_DEFAULT, + LZMA_LCLP_MIN, + LZMA_LCLP_MAX, + LZMA_LC_DEFAULT, + LZMA_LP_DEFAULT, + LZMA_PB_MIN, + LZMA_PB_MAX, + LZMA_PB_DEFAULT, + LZMA_BACKWARD_SIZE_MIN, + LZMA_BACKWARD_SIZE_MAX, + LZMA_VLI_MAX, + LZMA_VLI_UNKNOWN, + LZMA_VLI_BYTES_MAX, + LZMA_FILTER_X86, + LZMA_FILTER_POWERPC, + LZMA_FILTER_IA64, + LZMA_FILTER_ARM, + LZMA_FILTER_ARMTHUMB, + LZMA_FILTER_SPARC, + LZMA_FILTER_ARM64, + LZMA_FILTER_DELTA, + LZMA_FILTER_RISCV, + LZMA_FILTER_LZMA1, + LZMA_FILTER_LZMA2, + LZMA_STREAM_HEADER_SIZE, + ); +} + +#[test] +fn api_constant_types_match_c_backend() { + fn assert_same_type(_: T, _: T) {} + + macro_rules! assert_const_type_eq { + ($($name:ident),+ $(,)?) => { + $( + assert_same_type(c_sys::$name, rs_sys::$name); + )+ + }; + } + + assert_const_type_eq!( + LZMA_OK, + LZMA_STREAM_END, + LZMA_NO_CHECK, + LZMA_UNSUPPORTED_CHECK, + LZMA_GET_CHECK, + LZMA_MEM_ERROR, + LZMA_MEMLIMIT_ERROR, + LZMA_FORMAT_ERROR, + LZMA_OPTIONS_ERROR, + LZMA_DATA_ERROR, + LZMA_BUF_ERROR, + LZMA_PROG_ERROR, + LZMA_SEEK_NEEDED, + LZMA_RUN, + LZMA_SYNC_FLUSH, + LZMA_FULL_FLUSH, + LZMA_FULL_BARRIER, + LZMA_FINISH, + LZMA_CHECK_NONE, + LZMA_CHECK_CRC32, + LZMA_CHECK_CRC64, + LZMA_CHECK_SHA256, + LZMA_MODE_FAST, + LZMA_MODE_NORMAL, + LZMA_MF_HC3, + LZMA_MF_HC4, + LZMA_MF_BT2, + LZMA_MF_BT3, + LZMA_MF_BT4, + LZMA_TELL_NO_CHECK, + LZMA_TELL_UNSUPPORTED_CHECK, + LZMA_TELL_ANY_CHECK, + LZMA_IGNORE_CHECK, + LZMA_CONCATENATED, + LZMA_PRESET_DEFAULT, + LZMA_PRESET_LEVEL_MASK, + LZMA_PRESET_EXTREME, + LZMA_DICT_SIZE_MIN, + LZMA_DICT_SIZE_DEFAULT, + LZMA_LCLP_MIN, + LZMA_LCLP_MAX, + LZMA_LC_DEFAULT, + LZMA_LP_DEFAULT, + LZMA_PB_MIN, + LZMA_PB_MAX, + LZMA_PB_DEFAULT, + LZMA_BACKWARD_SIZE_MIN, + LZMA_BACKWARD_SIZE_MAX, + LZMA_VLI_MAX, + LZMA_VLI_UNKNOWN, + LZMA_VLI_BYTES_MAX, + LZMA_FILTER_X86, + LZMA_FILTER_POWERPC, + LZMA_FILTER_IA64, + LZMA_FILTER_ARM, + LZMA_FILTER_ARMTHUMB, + LZMA_FILTER_SPARC, + LZMA_FILTER_ARM64, + LZMA_FILTER_DELTA, + LZMA_FILTER_RISCV, + LZMA_FILTER_LZMA1, + LZMA_FILTER_LZMA2, + LZMA_STREAM_HEADER_SIZE, + ); +} + +#[test] +fn api_type_layout_matches_c_backend() { + macro_rules! assert_layout_eq { + ($name:ident) => { + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::(), + "size mismatch: {}", + stringify!($name) + ); + assert_eq!( + std::mem::align_of::(), + std::mem::align_of::(), + "align mismatch: {}", + stringify!($name) + ); + }; + } + + assert_layout_eq!(lzma_bool); + assert_layout_eq!(lzma_ret); + assert_layout_eq!(lzma_action); + assert_layout_eq!(lzma_check); + assert_layout_eq!(lzma_vli); + assert_layout_eq!(lzma_mode); + assert_layout_eq!(lzma_match_finder); + assert_layout_eq!(lzma_allocator); + assert_layout_eq!(lzma_stream); + assert_layout_eq!(lzma_filter); + assert_layout_eq!(lzma_options_lzma); + assert_layout_eq!(lzma_stream_flags); + assert_layout_eq!(lzma_options_bcj); + + #[cfg(feature = "parallel")] + assert_layout_eq!(lzma_mt); + + // Opaque types can have intentionally different concrete representations. + let _: *mut rs_sys::lzma_internal = std::ptr::null_mut(); + let _: *mut c_sys::lzma_internal = std::ptr::null_mut(); + let _: *mut rs_sys::lzma_index = std::ptr::null_mut(); + let _: *mut c_sys::lzma_index = std::ptr::null_mut(); +} + +#[test] +fn api_functions_are_exported() { + macro_rules! assert_fn_exported { + ($($name:ident),+ $(,)?) => { + $( + let _ = c_sys::$name as *const () as usize; + let _ = rs_sys::$name as *const () as usize; + )+ + }; + } + + assert_fn_exported!( + lzma_code, + lzma_end, + lzma_get_progress, + lzma_memusage, + lzma_memlimit_get, + lzma_memlimit_set, + lzma_easy_encoder_memusage, + lzma_easy_decoder_memusage, + lzma_easy_encoder, + lzma_easy_buffer_encode, + lzma_stream_encoder, + lzma_alone_encoder, + lzma_stream_buffer_bound, + lzma_stream_buffer_encode, + lzma_stream_decoder, + lzma_auto_decoder, + lzma_alone_decoder, + lzma_lzip_decoder, + lzma_stream_buffer_decode, + lzma_check_is_supported, + lzma_check_size, + lzma_crc32, + lzma_crc64, + lzma_get_check, + lzma_filter_encoder_is_supported, + lzma_filter_decoder_is_supported, + lzma_filters_copy, + lzma_raw_encoder_memusage, + lzma_raw_decoder_memusage, + lzma_raw_encoder, + lzma_raw_decoder, + lzma_filters_update, + lzma_raw_buffer_encode, + lzma_raw_buffer_decode, + lzma_properties_size, + lzma_properties_encode, + lzma_properties_decode, + lzma_physmem, + lzma_cputhreads, + lzma_stream_header_encode, + lzma_stream_footer_encode, + lzma_stream_header_decode, + lzma_stream_footer_decode, + lzma_stream_flags_compare, + lzma_version_number, + lzma_version_string, + lzma_vli_encode, + lzma_vli_decode, + lzma_vli_size, + lzma_lzma_preset, + lzma_mf_is_supported, + lzma_index_buffer_decode, + lzma_index_uncompressed_size, + lzma_index_end, + ); + + #[cfg(feature = "parallel")] + assert_fn_exported!( + lzma_stream_encoder_mt_memusage, + lzma_stream_encoder_mt, + lzma_stream_decoder_mt, + lzma_mt_block_size, + ); +} + +#[inline] +unsafe fn c_encode_easy(input: &[u8]) -> (u32, Vec) { + let bound = c_sys::lzma_stream_buffer_bound(input.len()); + let mut out = vec![0u8; bound]; + let mut out_pos: usize = 0; + let ret = c_sys::lzma_easy_buffer_encode( + 6, + c_sys::LZMA_CHECK_CRC64, + ptr::null(), + input.as_ptr(), + input.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + out.truncate(out_pos); + (ret as u32, out) +} + +#[inline] +unsafe fn rs_encode_easy(input: &[u8]) -> (u32, Vec) { + let bound = rs_sys::lzma_stream_buffer_bound(input.len()); + let mut out = vec![0u8; bound]; + let mut out_pos: usize = 0; + let ret = rs_sys::lzma_easy_buffer_encode( + 6, + rs_sys::LZMA_CHECK_CRC64, + ptr::null(), + input.as_ptr(), + input.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + out.truncate(out_pos); + (ret as u32, out) +} + +#[inline] +unsafe fn c_decode_stream_buffer(input: &[u8], expected_size_hint: usize) -> (u32, Vec) { + let mut cap = expected_size_hint.max(input.len() * 6 + 128).max(256); + let max_cap = 64 * 1024 * 1024; + + loop { + let mut out = vec![0u8; cap]; + let mut memlimit = u64::MAX; + let mut in_pos = 0usize; + let mut out_pos = 0usize; + let ret = c_sys::lzma_stream_buffer_decode( + &mut memlimit, + 0, + ptr::null(), + input.as_ptr(), + &mut in_pos, + input.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + if ret as u32 == c_sys::LZMA_BUF_ERROR as u32 && cap < max_cap { + cap = (cap * 2).min(max_cap); + continue; + } + out.truncate(out_pos); + return (ret as u32, out); + } +} + +#[inline] +unsafe fn rs_decode_stream_buffer(input: &[u8], expected_size_hint: usize) -> (u32, Vec) { + let mut cap = expected_size_hint.max(input.len() * 6 + 128).max(256); + let max_cap = 64 * 1024 * 1024; + + loop { + let mut out = vec![0u8; cap]; + let mut memlimit = u64::MAX; + let mut in_pos = 0usize; + let mut out_pos = 0usize; + let ret = rs_sys::lzma_stream_buffer_decode( + &mut memlimit, + 0, + ptr::null(), + input.as_ptr(), + &mut in_pos, + input.len(), + out.as_mut_ptr(), + &mut out_pos, + out.len(), + ); + if ret as u32 == rs_sys::LZMA_BUF_ERROR as u32 && cap < max_cap { + cap = (cap * 2).min(max_cap); + continue; + } + out.truncate(out_pos); + return (ret as u32, out); + } +} + +fn deterministic_payload(case: usize) -> Vec { + let len = match case % 7 { + 0 => 0, + 1 => 1, + 2 => 3, + 3 => 31, + 4 => 257, + 5 => 4096, + _ => 16384, + }; + let mut x = (0x9E3779B97F4A7C15u64 ^ (case as u64).wrapping_mul(0xD6E8FEB86659FD93)).max(1); + let mut out = Vec::with_capacity(len); + for _ in 0..len { + x ^= x >> 12; + x ^= x << 25; + x ^= x >> 27; + out.push((x.wrapping_mul(0x2545F4914F6CDD1D) & 0xFF) as u8); + } + out +} + +#[test] +fn differential_roundtrip_across_backends() { + for case in 0..128usize { + let input = deterministic_payload(case); + unsafe { + let (c_enc_ret, c_encoded) = c_encode_easy(&input); + let (rs_enc_ret, rs_encoded) = rs_encode_easy(&input); + assert_eq!( + c_enc_ret, rs_enc_ret, + "encoder ret mismatch at case {case}: c={c_enc_ret} rs={rs_enc_ret}" + ); + assert_eq!( + c_enc_ret, + c_sys::LZMA_OK as u32, + "C encoder failed at case {case} with ret {c_enc_ret}" + ); + + let (c_from_c_ret, c_from_c) = c_decode_stream_buffer(&c_encoded, input.len()); + let (rs_from_c_ret, rs_from_c) = rs_decode_stream_buffer(&c_encoded, input.len()); + let (c_from_rs_ret, c_from_rs) = c_decode_stream_buffer(&rs_encoded, input.len()); + let (rs_from_rs_ret, rs_from_rs) = rs_decode_stream_buffer(&rs_encoded, input.len()); + + assert_eq!( + c_from_c_ret, rs_from_c_ret, + "decode(c_encoded) ret mismatch at case {case}: c={c_from_c_ret} rs={rs_from_c_ret}" + ); + assert_eq!( + c_from_rs_ret, rs_from_rs_ret, + "decode(rs_encoded) ret mismatch at case {case}: c={c_from_rs_ret} rs={rs_from_rs_ret}" + ); + + assert_eq!( + c_from_c, input, + "C decode(C encode) payload mismatch at case {case}" + ); + assert_eq!( + rs_from_c, input, + "RS decode(C encode) payload mismatch at case {case}" + ); + assert_eq!( + c_from_rs, input, + "C decode(RS encode) payload mismatch at case {case}" + ); + assert_eq!( + rs_from_rs, input, + "RS decode(RS encode) payload mismatch at case {case}" + ); + } + } +} + +#[test] +fn differential_error_codes_on_invalid_corpus() { + let files_dir = Path::new("liblzma-sys/xz/tests/files"); + for entry in fs::read_dir(files_dir).expect("read xz test corpus directory") { + let path = entry.expect("dir entry").path(); + if path.extension().and_then(|s| s.to_str()) != Some("xz") { + continue; + } + + let filename = path.file_name().and_then(|s| s.to_str()).unwrap_or(""); + if !(filename.starts_with("bad") || filename.starts_with("unsupported")) { + continue; + } + if filename.contains("unsupported-check") { + // This is implementation-defined in existing tests. + continue; + } + + let data = fs::read(&path).expect("read corpus file"); + unsafe { + let (c_ret, _) = c_decode_stream_buffer(&data, 4096); + let (rs_ret, _) = rs_decode_stream_buffer(&data, 4096); + assert_eq!( + c_ret, + rs_ret, + "error ret mismatch for {}: c={} rs={}", + path.display(), + c_ret, + rs_ret + ); + } + } +}